Skip to main content

Consul — Service Mesh & Service Discovery Guide

Discover services, enforce health checks, and secure inter-service communication with mTLS zero-trust networking — HashiCorp Consul runs anywhere from bare metal to Kubernetes.

✓ Service discovery (DNS + API) ✓ mTLS service mesh (Envoy) ✓ Intentions (zero-trust) ✓ Distributed KV store

What is HashiCorp Consul?

HashiCorp Consul is a distributed systems tool that provides service discovery, health checking, key-value storage, and service mesh networking in a single unified platform. Released in 2014, Consul was designed from the ground up for dynamic, large-scale distributed environments where services come and go constantly. Unlike static load balancers or DNS with long TTLs, Consul provides real-time service registries that immediately reflect the actual state of your infrastructure.

Consul agents run on every node in your infrastructure — either as servers (which form the consensus cluster and hold state) or clients (which register local services, run health checks, and forward queries to servers). The recommended production setup is 3 or 5 server nodes for high availability via Raft consensus, with client agents on every host. Consul clusters can be federated across data centers, enabling multi-region service discovery and network segmentation.

Key Features

Service Registration

# /etc/consul.d/web-api.json
{
  "service": {
    "id": "web-api-1",
    "name": "web-api",
    "tags": ["v2", "primary"],
    "address": "10.0.1.10",
    "port": 8080,
    "meta": {
      "version": "2.1.0",
      "environment": "production"
    },
    "checks": [
      {
        "id": "api-http",
        "name": "HTTP health check",
        "http": "http://localhost:8080/health",
        "interval": "10s",
        "timeout": "2s"
      },
      {
        "id": "api-tcp",
        "name": "TCP connectivity",
        "tcp": "localhost:8080",
        "interval": "30s"
      }
    ],
    "connect": {
      "sidecar_service": {
        "proxy": {
          "upstreams": [
            {
              "destination_name": "postgres",
              "local_bind_port": 5432
            },
            {
              "destination_name": "redis",
              "local_bind_port": 6379
            }
          ]
        }
      }
    }
  }
}

Service Discovery CLI & DNS

# Query healthy service instances via API
curl http://127.0.0.1:8500/v1/catalog/service/web-api?passing=true

# DNS lookup — resolves to healthy instance IPs
dig @127.0.0.1 -p 8600 web-api.service.consul

# Filter by tag
dig @127.0.0.1 -p 8600 v2.web-api.service.consul

# Query a specific datacenter
dig @127.0.0.1 -p 8600 web-api.service.us-east-1.consul

# Register a service dynamically via API
curl -X PUT http://127.0.0.1:8500/v1/agent/service/register \
  -d '{"Name":"my-service","Port":9000,"Check":{"HTTP":"http://localhost:9000/health","Interval":"10s"}}'

# List all registered services
consul catalog services

# Watch for changes (long-poll, returns on any change)
consul watch -type=service -service=web-api cat

Service Mesh Intentions

# Allow web frontend to call the API service
consul intention create web-frontend web-api

# Allow API to call the database
consul intention create web-api postgres

# Deny all traffic from external services (default deny is preferred)
consul intention create -deny '*' postgres

# List all intentions
consul intention list

# Intentions via config entry (declarative, version-controlled)
# intentions.hcl
Kind = "service-intentions"
Name = "web-api"
Sources = [
  {
    Name       = "web-frontend"
    Action     = "allow"
  },
  {
    Name   = "*"
    Action = "deny"
  }
]

consul config write intentions.hcl

KV Store Operations

# Write and read key-value pairs
consul kv put config/myapp/db_host postgres.service.consul
consul kv put config/myapp/max_connections 100
consul kv get config/myapp/db_host

# Get with metadata (ModifyIndex for CAS operations)
consul kv get -detailed config/myapp/db_host

# List all keys under a prefix
consul kv get -recurse config/myapp/

# Delete a key
consul kv delete config/myapp/old_key

# Watch for changes (blocks until key changes)
consul watch -type=key -key=config/myapp/db_host cat

# Atomic compare-and-swap (CAS) — only update if ModifyIndex matches
consul kv put -cas -modify-index=42 config/myapp/db_host new-value

Consul vs Service Mesh Alternatives

Feature Consul Istio Linkerd AWS App Mesh Cilium
Platform Any (VMs, K8s, bare metal) Kubernetes-focused Kubernetes only AWS / EKS Kubernetes (eBPF)
Service discovery Yes (DNS + API) K8s DNS + Istio K8s DNS Cloud Map K8s DNS
Data plane Envoy Envoy Linkerd2-proxy (Rust) Envoy eBPF (no sidecar)
Complexity Medium High Low-Medium Low (managed) Medium
KV store Yes (built-in) No No No No
Multi-datacenter Yes (native WAN) Yes (complex) Limited AWS regions Cluster mesh

Use Cases

Pros and Cons

Pros

  • ✓ Works on VMs, bare metal, and Kubernetes — not K8s-only
  • ✓ Batteries included: discovery + health + mesh + KV in one tool
  • ✓ Native multi-datacenter and multi-region federation
  • ✓ DNS interface requires zero application changes for discovery
  • ✓ Simpler than Istio for most microservices use cases
  • ✓ HashiCorp ecosystem integration: Vault, Terraform, Nomad

Cons

  • ✗ Requires running and operating Consul server cluster
  • ✗ Less L7 traffic management features than Istio
  • ✗ Consul Enterprise needed for advanced features (namespaces, audit)
  • ✗ Envoy sidecar adds resource overhead per service instance
  • ✗ Raft consensus requires careful sizing (3 or 5 server nodes)
  • ✗ Learning curve for ACLs, intentions, and config entries

Frequently Asked Questions

What is Consul and what problems does it solve?▼

Consul is a multi-networking tool by HashiCorp that solves three interconnected problems in distributed systems: service discovery (how do services find each other?), health checking (which instances are healthy right now?), and service mesh networking (how do services communicate securely?). Without Consul, teams hardcode service addresses, manage health monitoring separately, and struggle to enforce network policies between microservices. Consul provides a single control plane that handles all three, with a distributed, highly available architecture that works across data centers and clouds.

How does Consul service discovery work?▼

Services register themselves with Consul either via a JSON service definition file (static registration) or via the Consul API (dynamic registration). Consul stores the registration and continuously runs health checks. Consumers discover services via DNS (my-service.service.consul resolves to healthy instance IPs) or the HTTP API (GET /v1/catalog/service/my-service). Consul automatically filters out unhealthy instances from DNS responses, so clients always get a list of healthy endpoints. This eliminates hardcoded service addresses and enables zero-config service discovery in dynamic environments.

What are Consul intentions and how do they implement zero-trust networking?▼

Intentions define which services are allowed to communicate with each other in the service mesh. An intention is a source-destination policy: 'web can call api', 'api can call database', 'external DENY all'. By default in a new Consul deployment, all traffic is denied unless explicitly allowed. Intentions are enforced by Envoy sidecars using mTLS — the sidecar on the receiving service checks the client's certificate identity (SPIFFE ID) against intentions. This implements zero-trust: services cannot communicate just because they're in the same network; they must have an explicit allow intention.

What is Consul Connect and how does the Envoy sidecar work?▼

Consul Connect is the service mesh feature. Each service instance gets an Envoy proxy sidecar that Consul configures automatically. Outbound traffic from the service goes to the local Envoy proxy, which looks up the destination service in Consul's catalog, gets its address, establishes a mTLS connection to the destination's Envoy sidecar, and forwards the request. The application only connects to localhost — it never needs to know service addresses or manage TLS certificates. Consul issues short-lived mTLS certificates via its built-in CA, rotating them automatically.

How does Consul KV store differ from other distributed KV stores?▼

Consul's KV store is a distributed, consistent key-value store built on Raft consensus. Unlike Redis (designed for caching, eventual consistency) or etcd (Kubernetes-focused), Consul KV is designed for configuration management and coordination in service-oriented architectures. It integrates natively with Consul watches (react to KV changes in real time), ACL policies, and Consul Template (render config files from KV values). It is not designed for high-throughput or large values — use it for configuration data, feature flags, and distributed coordination, not large blob storage.

What is Consul Template and when should I use it?▼

Consul Template is a daemon that watches Consul's KV store and service catalog for changes, then renders templates to files and optionally runs a command when they change. For example: watch for changes to the list of healthy backend servers, render an nginx upstream config file, then reload nginx. This eliminates the need to restart services to pick up configuration changes. Consul Template is most useful for legacy applications that read config from files rather than the Consul API, or for generating load balancer configurations dynamically.

Share this tool: X / Twitter LinkedIn
✓ 60,000+ developers use DevPlaybook ★★★★★ 4.8 / 5 on Gumroad ✓ MIT licensed · Instant download ✓ No login required

Related Products

on Gumroad

You Might Also Need

More Free Tools

Enjoying this tool? Get more like it.

Weekly developer tool guides, productivity playbooks & AI tricks. Free. No spam.

DevPlaybook Pro 7 days free

Unlock AI-Powered Dev Tools

  • ⚡ AI Code Review, Doc Generator & SQL Builder
  • ⚡ All premium templates & early access
  • ⚡ Member discounts on Gumroad products
Start Free Trial →

$9/mo after trial · Cancel anytime

Want the full toolkit?

Get DevPlaybook Pro

Every template, guide, boilerplate, and automation script in one bundle. 13 premium products — grab them all at once and save big.

$79
$241 separately Save $162 (67% off)
Get DevPlaybook Pro — $79 →

MIT licensed · Instant download · No subscription

See what's included → Browse all deals →