Open-Source Wikis

/

Consul

/

Consul

/

Architecture

hashicorp/consul

Architecture

Consul is a single Go binary (consul) that runs in one of two modes — agent (client) or server — plus a CLI. This page maps the runtime topology and the in-process layers.

Cluster topology

Every node in a datacenter runs an agent. A small set (typically 3 or 5) run as servers and form a Raft consensus group. Servers from different datacenters federate over WAN gossip and forward RPCs through the WAN pool.

graph TB
    subgraph DC1["Datacenter A (LAN gossip)"]
        A1[Client agent<br/>app+sidecar] --> SRV1[Server 1<br/>Raft leader]
        A2[Client agent<br/>app+sidecar] --> SRV1
        A3[Client agent<br/>app+sidecar] --> SRV1
        SRV1 -.Raft.- SRV2[Server 2]
        SRV1 -.Raft.- SRV3[Server 3]
    end
    subgraph DC2["Datacenter B (LAN gossip)"]
        B1[Client agent] --> SRV4[Server 1]
        SRV4 -.Raft.- SRV5[Server 2]
        SRV4 -.Raft.- SRV6[Server 3]
    end
    SRV1 ==WAN gossip + RPC forward==> SRV4
    SRV2 -.WAN.- SRV5
    SRV3 -.WAN.- SRV6

LAN gossip and WAN gossip are implemented on top of HashiCorp's Serf and memberlist libraries. The server-side Serf handlers live in agent/consul/server_serf.go and agent/consul/client_serf.go; WAN federation logic lives under agent/consul/wanfed/ and agent/consul/leader_federation_state_ae.go.

In-process architecture

graph TB
    subgraph CLI["consul CLI (main.go → command/*)"]
        CMD[Cobra-style command tree<br/>command/registry.go]
    end

    subgraph Agent["Agent (agent/agent.go)"]
        HTTP[HTTP server<br/>agent/http.go]
        DNS[DNS server<br/>agent/dns.go]
        Local[Local state<br/>agent/local/]
        Cache[RPC cache + materialized views<br/>agent/cache, agent/submatview]
        ProxyCfg[Proxy config manager<br/>agent/proxycfg/]
        XDS[xDS gRPC server<br/>agent/xds/]
        Checks[Health checks<br/>agent/checks/]
    end

    subgraph Server["Server-only (agent/consul/)"]
        Raft[Raft + FSM<br/>agent/consul/fsm/]
        State[(MemDB state store<br/>agent/consul/state/)]
        Endpoints[RPC endpoints<br/>*_endpoint.go]
        GRPCInt[Internal gRPC<br/>agent/grpc-internal/]
        GRPCExt[External gRPC<br/>agent/grpc-external/]
        Leader[Leader loops<br/>agent/consul/leader*.go]
    end

    CMD --> HTTP
    HTTP --> Endpoints
    DNS --> Endpoints
    HTTP --> Local
    Local <--> Endpoints
    ProxyCfg --> Cache
    XDS --> ProxyCfg
    Checks --> Local
    Endpoints --> State
    Endpoints --> Raft
    Raft --> State
    Leader --> State
    GRPCExt --> Endpoints
    GRPCInt --> State

Layered responsibilities

Layer Code Role
CLI command/, main.go Parse user commands, talk to a running agent over HTTP
HTTP API agent/http.go, agent/*_endpoint.go REST surface that the CLI, UI, and integrations consume
DNS API agent/dns.go, agent/dns/ DNS interface for service and node lookups
Agent runtime agent/agent.go (157k lines, the central object), agent/setup.go Wires every subsystem into one Agent struct, handles config reload
Local state agent/local/ Tracks services, checks, and proxies on this node and reconciles with servers via anti-entropy (agent/ae/)
RPC cache agent/cache/, agent/cache-types/, agent/submatview/ Caches RPC results and supports streaming updates so blocking queries don't hammer the leader
Proxy config agent/proxycfg/, agent/proxycfg-glue/, agent/proxycfg-sources/ Computes the proxy snapshot (clusters, listeners, routes, endpoints, secrets) for each registered Connect proxy
xDS server agent/xds/ Translates proxy snapshots into Envoy xDS resources and streams them over delta-xDS
Server core agent/consul/server.go (68k LoC), agent/consul/client.go Joins Raft, exposes RPC, runs leader-only loops
Raft + FSM agent/consul/fsm/, agent/consul/raft_handle.go Applies replicated log entries to the in-memory state store
State store agent/consul/state/ (built on go-memdb) The authoritative in-memory database with watch indices
RPC endpoints agent/consul/*_endpoint.go (catalog, health, kvs, acl, intention, connect_ca, prepared_query, txn, ...) Net/RPC handlers that read/write through Raft for writes and from MemDB for reads
gRPC agent/grpc-internal/, agent/grpc-external/, proto-public/ (DNS, ACL, ConnectCA, dataplane, server discovery, resource, multicluster) Internal control-plane gRPC and external public APIs
V2 resource framework internal/resource/, internal/controller/, internal/storage/ Generic resource/controller machinery used by the next-generation v2 catalog and multicluster APIs
Service mesh agent/connect/, connect/, agent/consul/leader_connect_ca.go, agent/consul/connect_ca_endpoint.go CA management, leaf cert issuance, intentions, identity
Auto-config agent/auto-config/, agent/consul/auto_config_endpoint.go Bootstrap and TLS material distribution to client agents
Snapshots agent/consul/fsm/snapshot.go, snapshot/ Save/restore the Raft FSM to a binary archive

Read and write paths

sequenceDiagram
    participant App
    participant Agent as Local agent
    participant Server as Server (follower)
    participant Leader as Server (Raft leader)
    participant State as MemDB state store

    App->>Agent: HTTP PUT /v1/kv/foo
    Agent->>Server: RPC KVS.Apply
    Server->>Leader: forward (RPC, if not leader)
    Leader->>Leader: Raft.Apply(log)
    Leader->>State: FSM applies entry
    State-->>Leader: index updated
    Leader-->>Server: ok
    Server-->>Agent: ok
    Agent-->>App: 200 OK

    App->>Agent: GET /v1/kv/foo?index=42
    Agent->>Server: RPC KVS.Get (blocking)
    Server->>State: blocking query (waits for index > 42)
    State-->>Server: new value, index 43
    Server-->>Agent: payload
    Agent-->>App: 200 OK

Writes go through Raft. Reads go through MemDB and use blocking queries (long polling on a memdb watch index). Reads can also be served via the gRPC streaming subscribe backend (agent/consul/subscribe_backend.go, agent/consul/stream/) and the materialized-view cache (agent/submatview/).

Service mesh data path

graph LR
    Manager[proxycfg.Manager<br/>agent/proxycfg/manager.go] -->|snapshot| XDS
    XDS[xDS server<br/>agent/xds/server.go,delta.go] -->|CDS/EDS/LDS/RDS/SDS<br/>delta xDS over gRPC| Envoy
    LeafCert[leafcert<br/>agent/leafcert/] -->|leaf cert| Manager
    CA[Connect CA<br/>agent/consul/leader_connect_ca.go] -->|root CA| Manager
    Catalog[Catalog/health watches] -->|targets, endpoints| Manager
    Intentions[Intentions<br/>agent/consul/intention_endpoint.go] -->|RBAC rules| Manager
    Manager -->|extensions runtime| Ext[envoyextensions/<br/>extensionruntime]
    Ext --> XDS

The proxy config manager fetches everything an Envoy needs (clusters, endpoints, routes, secrets, intentions, JWT providers, gateway state, ...), assembles a ConfigSnapshot, and hands it to the xDS server, which serializes Envoy resources and streams them with the delta-xDS protocol.

Sub-modules

The repo is a Go workspace. Each of these has its own go.mod:

Module Purpose
Root (github.com/hashicorp/consul) The consul binary (agent, server, CLI)
api/ Public Go HTTP client used by the CLI, integrations, and external Go apps
sdk/ Test helpers: freeport, iptables, testutil, certificate helpers, etc.
envoyextensions/ Envoy extension framework + bundled extensions and xdscommon
proto-public/ Public protobuf packages (pbacl, pbconnectca, pbdataplane, pbdns, pbresource, pbserverdiscovery, ...)
troubleshoot/ Library used by consul troubleshoot to diagnose mesh wiring

See Packages for the per-module deep dive.

Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.

Architecture – Consul wiki | Factory