Consul API

The official Go client SDK for talking to a Consul cluster's HTTP API — service discovery, health checks, KV storage, and service mesh config.

SDK
Go
vv1.34.4
30,058stars
Mozilla Public License 2.0

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum.How we score it →
96/100Excellent
Development Activity96
Maintenance96
Community92
Maturity60
Momentum40

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation.How we score it →
78/100Good
Architecture80
Code Quality88
Innovation68
Learning Curve75

The api package is HashiCorp’s official Go client for Consul, the distributed service-mesh and service-discovery platform. Rather than shelling out to the consul CLI or hand-rolling HTTP calls, Go services import this package to talk directly to a running Consul agent or server over its HTTP API — registering services, running health checks, reading and writing key-value data, and managing ACLs, sessions, and service-mesh configuration entries.

It is maintained as its own Go module (github.com/hashicorp/consul/api) inside the main Consul repository, with its own go.mod, its own MPL-2.0 license, and a stable API surface that is versioned independently of the Consul server binary it talks to — the same pattern used by other infrastructure vendors (AWS, Google Cloud) for their service client SDKs, distinct from the BUSL-licensed Consul server/agent code that lives alongside it in the monorepo.

Each Consul subsystem gets its own typed sub-client returned from the shared Clientclient.KV(), client.Agent(), client.Health(), client.Catalog(), client.ACL(), client.Operator(), and more — so applications only need to construct one client and pull the pieces of the API they actually use. Higher-level coordination primitives like distributed locks and semaphores are built on top of the same KV and Session endpoints, giving Go applications leader-election and mutual-exclusion primitives without a separate dependency.

What You Get

  • A single Client (built via NewClient/DefaultConfig) exposing typed sub-clients for every Consul subsystem — KV, Agent, Catalog, Health, ACL, Session, Operator, Connect, and more
  • Full read/write access to the KV store, including CAS operations and blocking queries for watching keys change
  • Service registration, deregistration, and health-check management through the local Agent API
  • Distributed coordination primitives — Lock and Semaphore — implemented on top of Consul sessions for leader election and mutual exclusion
  • Typed config-entry types for service-mesh resources (intentions, gateways, discovery chains, exported services, JWT providers, rate limits) so mesh config can be managed as Go structs instead of raw JSON/HCL
  • Consistent handling of Consul’s QueryOptions/WriteOptions (datacenter, token, consistency mode, blocking-query WaitIndex) across every endpoint

Common Use Cases

  • Service registration - a Go microservice registers itself and its health check with the local Consul agent on startup so other services can discover it
  • Dynamic configuration - an application reads and watches KV keys via blocking queries to pick up configuration changes without redeploying
  • Service discovery - client code queries the Catalog/Health APIs to find healthy instances of a dependency before making a request
  • Distributed leader election - a background job pool uses the Lock primitive so only one replica runs a given task at a time
  • Service-mesh automation - an operator tool creates and updates intentions, gateways, and other config entries to manage Consul Connect programmatically

Under The Hood

Architecture The package centers on a single Client (api.go) that holds connection config and a shared http.Client; every resource-specific file (kv.go, agent.go, catalog.go, health.go, acl.go, operator_.go, config_entry_.go, and roughly 40 others) exposes its own typed sub-client obtained from methods like client.KV() or client.Agent(), each one a thin, resource-oriented wrapper that builds a request via Client.newRequest, sets query/write options (setQueryOptions/setWriteOptions), and executes it through the shared doRequest/toHTTP path. Lock and Semaphore are the one layer of real composition in the codebase — both are built entirely on top of the KV and Session APIs rather than any separate coordination protocol, so distributed-locking semantics live in the client rather than requiring server-side support. There is no dependency injection or internal service layering beyond this: because every sub-client funnels through the same request/response helpers in api.go, a change to that core request path ripples across all ~50 resource files, making it a flat, request-oriented facade over Consul’s HTTP API rather than a layered application.

Tech Stack The module (github.com/hashicorp/consul/api, Go 1.26) is deliberately lightweight for a client library: hashicorp/go-cleanhttp for a clean, non-shared http.Client, hashicorp/go-rootcerts for TLS CA handling, hashicorp/go-hclog for logging, hashicorp/go-multierror and hashicorp/go-uuid for error aggregation and ID generation, plus a replace directive pointing at the sibling hashicorp/consul/sdk module for shared test utilities. It depends on almost nothing from the Consul server itself — the split into its own go.mod keeps it installable and versioned independently of the Consul agent/server binaries in the same repository.

Code Quality Testing is extensive: roughly 39 _test.go files sit alongside 53 implementation files, using stretchr/testify’s require package for assertions and a shared makeClient/makeClientWithConfig helper (backed by hashicorp/consul/sdk’s testutil.TestServer) that spins up a real local Consul agent per test rather than mocking the HTTP layer — giving genuine integration coverage of the wire format, not just the Go-side plumbing. A dedicated go-tests.yml GitHub Actions workflow runs this suite in CI. Naming is consistent with Go conventions (exported types like KVPair, AgentServiceRegistration map directly to Consul’s HTTP JSON shapes), and errors are returned rather than swallowed throughout the request path.

What Makes It Unique Unlike a generic HTTP client, this package encodes Consul’s specific semantics as first-class Go concepts — blocking queries via WaitIndex/WaitTime for efficient long-poll watches, consistency modes (stale/consistent) as query options, and CAS-based KV writes — so callers get Consul’s actual consistency model instead of a bare REST wrapper. Building distributed locks and semaphores directly on the KV/Session primitives (rather than a bespoke coordination RPC) is a deliberate design choice shared with etcd/ZooKeeper-style clients, and keeping this SDK in its own Go module inside the Consul monorepo, under MPL-2.0 while the server code is BUSL-licensed, is the same separation strategy used for other infrastructure vendors’ client libraries.

Join founders buildingwith open source

Opinionated takes, migration guides, cost-saving tips, and insights from the open source ecosystem.

Subscribe on Substack
Join 750+ subscribers

Search