Using Consul Prepared Queries for Dynamic Service Lookup Without Redeploying Clients
Learn how Consul Prepared Queries let you change service‑lookup filters (tags, version, health) without redeploying every client, with a worked example, trade‑offs, and practical steps.
11 Jul 2026, 22:28 UTC

The problem: changing service selection without touching every client
Imagine you have a fleet of services that call a Consul‑registered web service. Today you route to all healthy instances, but tomorrow you need to send traffic only to instances tagged production or running a specific version. Updating each client’s code or configuration to reflect the new filter would be tedious and error‑prone.
What Consul Prepared Queries give you
A Prepared Query is a stored, parameterized lookup definition that lives in the Consul catalog. You define it once (service name, filters, optional TTL) and Consul assigns it a stable ID. Clients can then resolve that ID via DNS (<id>.service.consul) or HTTP (/v1/query/<id>/execute) just like any other service. Changing the filter later only requires updating the Prepared Query; clients keep using the same name.
Worked example: create a query for healthy production web instances
- Check permissions – You need an ACL token with
query:writeto create the query andquery:readto execute it. If you are using the defaultmastertoken in a dev environment, this is already satisfied. In production, create a token policy like:
key "" { policy = "write" }
key "query/" { policy = "write" }
key "query/" { policy = "read" }
- Create the query – Run this on any Consul client or server where the CLI is configured with the appropriate token:
consul query create \
-name=prod-web \
-service=web \
-tag=production \
-ttl=20s \
-token=<ACL-TOKEN>
The command returns a JSON payload that includes the generated ID, e.g. "ID":"a1b2c3d4-5678-90ab-cdef-1234567890ab". You can also view it in the Consul UI under Prepared Queries.
- Execute via HTTP – Use curl (or any HTTP client) with the same token for read access:
curl -s \
-H "X-Consul-Token: <ACL-TOKEN>" \
http://localhost:8500/v1/query/a1b2c3d4-5678-90ab-cdef-1234567890ab/execute
The response is a JSON array of nodes that match web, have the production tag, and are in the passing health state. No need to parse tags or health yourself.
- Execute via DNS – Point your application’s resolver at the Consul DNS port (8600 by default):
dig @127.0.0.1 -p 8600 a1b2c3d4-5678-90ab-cdef-1234567890ab.service.consul +short
This returns the IP addresses of the same filtered set. Because the query is cached per‑agent, the TTL you set (20 s in the example) controls how quickly a change to the filter propagates.
Trade‑off and limitation
Prepared Queries add a small indirection layer:
- Latency – Each DNS or HTTP request hits the Consul agent, which may forward the query to the servers; expect an extra few milliseconds compared to a direct service lookup.
- Cache staleness – Results are cached per agent for the duration of the TTL. If you need near‑real‑time reflection of tag changes, lower the TTL (e.g., 5 s) or bypass the cache with the
?stale=falseflag on the HTTP endpoint. - ACL management – Anyone who can read a Prepared Query can see the underlying filter; protect query definitions with appropriate
query:read/query:writepolicies.
These factors are usually acceptable for service‑discovery use cases where the lookup name is stable and the filter changes infrequently (e.g., per‑environment or per‑tenant routing).
Actionable closing
If you face a scenario where service selection logic must evolve without touching every client:
- Define a Prepared Query that captures the current filter (service, tags, node meta, health).
- Roll out the stable DNS or HTTP name to your services.
- When the filter changes, update the Prepared Query via
consul query updateor the UI; clients automatically see the new set after the TTL expires. - Monitor query execution latency and cache hit‑rate in the Consul telemetry (
consul querymetrics) to ensure the trade‑off stays within your SLA.
By centralizing the lookup logic in Consul, you gain a single point of change while keeping client configuration simple and version‑free.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.