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.
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 Registry — real-time catalog of services with tags, metadata, and addresses
- Health Checks — HTTP, TCP, gRPC, script, and TTL checks; unhealthy instances filtered from DNS
- DNS Interface — service-name.service.consul resolves to healthy instance IPs, zero client changes
- HTTP API — query catalog, KV store, and agent programmatically from any language
- Intentions — declarative access control between services, enforced by Envoy mTLS
- Envoy Sidecar (Connect) — transparent L7 proxy with automatic mTLS, observability, and retries
- KV Store — distributed, consistent key-value storage for configuration and coordination
- Multi-datacenter — federate clusters across regions with WAN gossip protocol
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
- Microservices architectures where services need to discover each other dynamically without hardcoded IPs
- Hybrid cloud / multi-datacenter environments running both VMs and Kubernetes
- Zero-trust network segmentation — enforce which services can communicate via intentions
- Service mesh for organizations not yet fully on Kubernetes (Consul works on bare metal and VMs)
- Configuration distribution via KV store with Consul Template for dynamic config file generation
- Replacing static load balancer configs with real-time service-health-aware routing
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.
Related Products
on GumroadPremium Workflow Pack
Production-grade workflows, architecture guides, and deployment scripts for teams that ship. 10 advanced CI/CD workflows (blue-green, canary, E2E, security), 5 architecture deep-dives, code review checklist, PR process guide, and 5 battle-tested Bash deployment scripts.
Buy on Gumroad →GitHub Actions CI/CD Templates Pack
12 production-ready GitHub Actions workflow templates covering Node.js, Python, Docker, multi-environment deployments, security scanning, and auto-changelog. Copy, paste, ship.
Buy on Gumroad →Developer Productivity Bundle
Stop rebuilding the same setup every project. 51 VSCode snippets, 40 Git aliases, 5 Docker Compose stacks, 5 GitHub Actions workflows, 5 README templates, and a dotfiles kit. Set up a professional dev environment in under an hour.
Buy on Gumroad →You Might Also Need
Nomad Job Spec Builder
Generate HashiCorp Nomad job specification HCL from form inputs. Build service, batch, and system jobs with Docker/exec drivers, resources, and Consul service registration.
Open free tool →
Vault Policy Generator
Generate HashiCorp Vault HCL policies from path and capabilities form. Build least-privilege Vault policies for secrets access control.
Open free tool →
Infrastructure Cost Calculator
Compare and estimate monthly infrastructure costs for AWS EC2, Azure VMs, and Google Compute Engine. Add storage and data transfer for total monthly cloud cost.
Open free tool →
More Free Tools
Related Articles
AWS CDK vs Terraform vs Pulumi: Infrastructure as Code Comparison 2026
Complete comparison of AWS CDK, Terraform, and Pulumi for infrastructure as code in 2026 — language support, state management, multi-cloud, community, and when to use each.
Backstage Internal Developer Portal: Complete Setup Guide 2026
Learn how to set up Backstage IDP from scratch. Covers software catalog, TechDocs, plugins, CI/CD integration, and building a self-service developer platform your team will actually use.
Cilium Service Mesh vs Istio vs Linkerd: Kubernetes Networking 2026
Comprehensive comparison of Cilium, Istio, and Linkerd for Kubernetes service mesh in 2026. eBPF networking, performance benchmarks, mTLS, observability, and when to use each.
Ansible vs Chef vs Puppet: Configuration Management Tools Compared 2026
Ansible vs Chef vs Puppet — compare agentless vs agent-based architecture, YAML vs Ruby DSL, scalability, Windows support, and cloud integration. Find the right config management tool for 2026.
Docker Compose vs Kubernetes for Small Teams 2026
Should small teams use Docker Compose or Kubernetes in 2026? Compare production viability, K3s as a middle ground, Kompose migration, and the real costs of managed Kubernetes for teams under 20.
Enjoying this tool? Get more like it.
Weekly developer tool guides, productivity playbooks & AI tricks. Free. No spam.
Unlock AI-Powered Dev Tools
- ⚡ AI Code Review, Doc Generator & SQL Builder
- ⚡ All premium templates & early access
- ⚡ Member discounts on Gumroad products
$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.
MIT licensed · Instant download · No subscription
See what's included → Browse all deals →