# 13 — Discovery (Akka.Discovery)

## Overview

Akka.Discovery provides a pluggable service discovery API that allows cluster nodes to find each other dynamically. It supports multiple backends: configuration-based (static), Azure Table Storage, AWS EC2, Kubernetes DNS, and more. Discovery is used by Akka.Management's Cluster Bootstrap to automate cluster formation.

In the SCADA system's 2-node topology with static IPs, Discovery's dynamic capabilities are largely unnecessary — static seed nodes work well. However, understanding Discovery is valuable for future-proofing and for sites that may use DHCP or containerized deployments.

## When to Use

- If site deployments use DHCP or dynamic IP assignment (uncommon in industrial environments but possible)
- If the system is ever deployed in containers (Docker on Windows Server)
- For sites where node addresses may change due to infrastructure migration

## When Not to Use

- In the current architecture with static IPs/hostnames — static seed nodes in the Cluster configuration are simpler and more predictable
- For equipment discovery (finding machines on the network) — Akka.Discovery is for finding *cluster nodes*, not industrial equipment

## Design Decisions for the SCADA System

### Current Recommendation: Static Seed Nodes

For fixed 2-node deployments on Windows Server with known hostnames, static seed nodes (configured in [03-Cluster.md](./03-Cluster.md)) are the simplest and most reliable approach. No Discovery plugin is needed.

### Future Option: Config-Based Discovery

If the system needs a Discovery mechanism without external dependencies, use the built-in configuration-based discovery as a stepping stone:

```hocon
akka.discovery {
  method = config
  config {
    services {
      scada-cluster {
        endpoints = [
          "nodeA.scada.local:4053",
          "nodeB.scada.local:4053"
        ]
      }
    }
  }
}
```

This is functionally equivalent to static seed nodes but uses the Discovery API, making it easier to swap to a dynamic provider later.

### Future Option: Custom Discovery Provider

For sites with a central configuration management system (e.g., a site database that tracks which machines run the SCADA software), a custom Discovery provider could query that system to find cluster nodes:

```csharp
public class SiteDbDiscovery : ServiceDiscovery
{
    public override Task<Resolved> Lookup(Lookup lookup, TimeSpan resolveTimeout)
    {
        // Query site database for SCADA node addresses
        var nodes = _siteDb.GetScadaNodes();
        var targets = nodes.Select(n => new ResolvedTarget(n.Hostname, n.Port)).ToList();
        return Task.FromResult(new Resolved(lookup.ServiceName, targets));
    }
}
```

## Common Patterns

### Discovery + Cluster Bootstrap

If Discovery is adopted, pair it with Akka.Management's Cluster Bootstrap (see [14-Management.md](./14-Management.md)):

```csharp
akkaBuilder
    .WithAkkaManagement(port: 8558)
    .WithClusterBootstrap(
        serviceName: "scada-cluster",
        requiredContactPoints: 2);
```

### Fallback Chain

Aggregate Discovery allows chaining multiple discovery methods with fallback:

```hocon
akka.discovery {
  method = aggregate
  aggregate {
    discovery-methods = ["custom-site-db", "config"]
  }
}
```

## Anti-Patterns

### Using Discovery for a 2-Node Static Deployment

Adding Discovery and Cluster Bootstrap to a fixed 2-node deployment with known addresses adds complexity without benefit. The Discovery plugin, Management HTTP endpoint, and Bootstrap coordination all introduce additional failure points.

### Confusing Node Discovery with Equipment Discovery

Akka.Discovery finds *Akka.NET cluster nodes*. It does not discover industrial equipment on the network. OPC-UA has its own discovery mechanism (OPC-UA Discovery Server); the custom protocol presumably has its own registration or configuration approach.

## Configuration Guidance

For the current architecture, no Discovery configuration is needed. If adopted in the future:

```hocon
akka.discovery {
  method = config  # Or "azure", "aws", "kubernetes", etc.
  config {
    services {
      scada-cluster {
        endpoints = [
          "nodeA.scada.local:4053",
          "nodeB.scada.local:4053"
        ]
      }
    }
  }
}
```

## References

- Official Documentation: <https://getakka.net/articles/discovery/index.html>
- Azure Discovery: <https://github.com/akkadotnet/Akka.Management>
