1--- 2layout: api 3page_title: Prepared Queries - HTTP API 4sidebar_current: api-query 5description: |- 6 The /query endpoints manage and execute prepared queries in Consul. 7--- 8 9# Prepared Query HTTP Endpoint 10 11The `/query` endpoints create, update, destroy, and execute prepared queries. 12 13Prepared queries allow you to register a complex service query and then execute 14it later via its ID or name to get a set of healthy nodes that provide a given 15service. This is particularly useful in combination with Consul's 16[DNS Interface](/docs/agent/dns.html) as it allows for much richer queries than 17would be possible given the limited entry points exposed by DNS. 18 19See the [Geo Failover Guide](/docs/guides/geo-failover.html) for details and 20examples for using prepared queries to implement geo failover for services. 21 22See the ACL Guide's [prepared query rules](/docs/guides/acl.html#prepared-query-rules) 23section for more details about how prepared queries work with Consul's ACL system. 24 25### Prepared Query Templates 26 27Consul 0.6.4 and later support prepared query templates. These are created 28similar to static queries, except with some additional fields and features. 29Here is an example prepared query template: 30 31```json 32{ 33 "Template": { 34 "Type": "name_prefix_match", 35 "Regexp": "^geo-db-(.*?)-([^\\-]+?)$", 36 "RemoveEmptyTags": false 37 } 38} 39``` 40 41The `Template` structure configures a prepared query as a template instead of a 42static query. It has two fields: 43 44- `Type` is the query type, which must be `name_prefix_match`. This means that 45 the template will apply to any query lookup with a name whose prefix matches 46 the `Name` field of the template. In this example, any query for `geo-db` will 47 match this query. Query templates are resolved using a longest prefix match, 48 so it's possible to have high-level templates that are overridden for specific 49 services. Static queries are always resolved first, so they can also override 50 templates. 51 52- `Regexp` is an optional regular expression which is used to extract fields 53 from the entire name, once this template is selected. In this example, the 54 regular expression takes the first item after the "-" as the database name and 55 everything else after as a tag. See the 56 [RE2](https://github.com/google/re2/wiki/Syntax) reference for syntax of this 57 regular expression. 58 59- `RemoveEmptyTags` is optional, and if set to true, will cause the `Tags` list 60 inside the `Service` structure to be stripped of any empty strings. This defaults 61 to false, meaning that empty strings will remain in the list. This is useful 62 when interpolating into tags in a way where the tag is optional, and where 63 searching for an empty tag would yield no results from the query. 64 65All other fields of the query have the same meanings as for a static query, 66except that several interpolation variables are available to dynamically 67populate the query before it is executed. All of the string fields inside the 68`Service` structure are interpolated, with the following variables available: 69 70- `${name.full}` has the entire name that was queried. For example, a DNS lookup 71 for `geo-db-customer-primary.query.consul` in the example above would set this 72 variable to `geo-db-customer-primary`. 73 74- `${name.prefix}` has the prefix that matched. This would always be `geo-db` 75 for the example above. 76 77- `${name.suffix}` has the suffix after the prefix. For example, a DNS lookup 78 for `geo-db-customer-primary.query.consul` in the example above would set this 79 variable to `-customer-primary`. 80 81- `${match(N)}` returns the regular expression match at the given index N. The 0 82 index will have the entire match, and >0 will have the results of each match 83 group. For example, a DNS lookup for `geo-db-customer-primary.query.consul` in 84 the example above with a `Regexp` field set to `^geo-db-(.*?)-([^\-]+?)$` 85 would return `geo-db-customer-primary` for `${match(0)}`, `customer` for 86 `${match(1)}`, and `primary` for `${match(2)}`. If the regular expression 87 doesn't match, or an invalid index is given, then `${match(N)}` will return an 88 empty string. 89 90- `${agent.segment}` has the network segment (Enterprise-only) of the agent that 91 initiated the query. This can be used with the `NodeMeta` field to limit the results 92 of a query to service instances within its own network segment: 93 94 ```json 95 { 96 "Name": "", 97 "Template": { 98 "Type": "name_prefix_match" 99 }, 100 "Service": { 101 "Service": "${name.full}", 102 "NodeMeta": {"consul-network-segment": "${agent.segment}"} 103 } 104 } 105 ``` 106 This will map all names of the form `<service>.query.consul` over DNS to a query 107 that will select an instance of the service in the agent's own network segment. 108 109Using templates, it is possible to apply prepared query behaviors to many 110services with a single template. Here's an example template that matches any 111query and applies a failover policy to it: 112 113```json 114{ 115 "Name": "", 116 "Template": { 117 "Type": "name_prefix_match" 118 }, 119 "Service": { 120 "Service": "${name.full}", 121 "Failover": { 122 "NearestN": 3 123 } 124 } 125} 126``` 127 128This will match any lookup for `*.query.consul` and will attempt to find the 129service locally, and otherwise attempt to find that service in the next three 130closest datacenters. If ACLs are enabled, a catch-all template like this with 131an empty `Name` requires an ACL token that can write to any query prefix. Also, 132only a single catch-all template can be registered at any time. 133 134## Create Prepared Query 135 136This endpoint creates a new prepared query and returns its ID if it is created 137successfully. 138 139| Method | Path | Produces | 140| ------ | ---------------------------- | -------------------------- | 141| `POST` | `/query` | `application/json` | 142 143The table below shows this endpoint's support for 144[blocking queries](/api/index.html#blocking-queries), 145[consistency modes](/api/index.html#consistency-modes), 146[agent caching](/api/index.html#agent-caching), and 147[required ACLs](/api/index.html#acls). 148 149| Blocking Queries | Consistency Modes | Agent Caching | ACL Required | 150| ---------------- | ----------------- | ------------- | ------------- | 151| `NO` | `none` | `none` | `query:write` | 152 153### Parameters 154 155- `dc` `(string: "")` - Specifies the datacenter to query. This will default to 156 the datacenter of the agent being queried. This is specified as part of the 157 URL as a query parameter. 158 159- `Name` `(string: "")` - Specifies an optional friendly name that can be used 160 to execute a query instead of using its ID. 161 162- `Session` `(string: "")` - Specifies the ID of an existing session. This 163 provides a way to automatically remove a prepared query when the given session 164 is invalidated. If not given the prepared query must be manually removed when 165 no longer needed. 166 167- `Token` `(string: "")` - Specifies the ACL token to use each time the query is 168 executed. This allows queries to be executed by clients with lesser or even no 169 ACL Token, so this should be used with care. The token itself can only be seen 170 by clients with a management token. If the `Token` field is left blank or 171 omitted, the client's ACL Token will be used to determine if they have access 172 to the service being queried. If the client does not supply an ACL Token, the 173 anonymous token will be used. 174 175- `Service` `(Service: <required>)` - Specifies the structure to define the query's behavior. 176 177 - `Service` `(string: <required>)` - Specifies the name of the service to 178 query. 179 180 - `Failover` contains two fields, both of which are optional, and determine 181 what happens if no healthy nodes are available in the local datacenter when 182 the query is executed. It allows the use of nodes in other datacenters with 183 very little configuration. 184 185 - `NearestN` `(int: 0)` - Specifies that the query will be forwarded to up 186 to `NearestN` other datacenters based on their estimated network round 187 trip time using [Network Coordinates](/docs/internals/coordinates.html) 188 from the WAN gossip pool. The median round trip time from the server 189 handling the query to the servers in the remote datacenter is used to 190 determine the priority. 191 192 - `Datacenters` `(array<string>: nil)` - Specifies a fixed list of remote 193 datacenters to forward the query to if there are no healthy nodes in the 194 local datacenter. Datacenters are queried in the order given in the 195 list. If this option is combined with `NearestN`, then the `NearestN` 196 queries will be performed first, followed by the list given by 197 `Datacenters`. A given datacenter will only be queried one time during a 198 failover, even if it is selected by both `NearestN` and is listed in 199 `Datacenters`. 200 201 - `IgnoreCheckIDs` `(array<string>: nil)` - Specifies a list of check IDs that 202 should be ignored when filtering unhealthy instances. This is mostly useful 203 in an emergency or as a temporary measure when a health check is found to be 204 unreliable. Being able to ignore it in centrally-defined queries can be 205 simpler than de-registering the check as an interim solution until the check 206 can be fixed. 207 208 - `OnlyPassing` `(bool: false)` - Specifies the behavior of the query's health 209 check filtering. If this is set to false, the results will include nodes 210 with checks in the passing as well as the warning states. If this is set to 211 true, only nodes with checks in the passing state will be returned. 212 213 - `Near` `(string: "")` - Specifies a node to sort near based on distance 214 sorting using [Network Coordinates](/docs/internals/coordinates.html). The 215 nearest instance to the specified node will be returned first, and subsequent 216 nodes in the response will be sorted in ascending order of estimated 217 round-trip times. If the node given does not exist, the nodes in the response 218 will be shuffled. If unspecified, the response will be shuffled by default. 219 220 - `_agent` - Returns results nearest the agent servicing the request. 221 - `_ip` - Returns results nearest to the node associated with the source IP 222 where the query was executed from. For HTTP the source IP is the remote 223 peer's IP address or the value of the X-Forwarded-For header with the 224 header taking precedence. For DNS the source IP is the remote peer's IP 225 address or the value of the ENDS client IP with the EDNS client IP 226 taking precedence. 227 228 229 - `Tags` `(array<string>: nil)` - Specifies a list of service tags to filter 230 the query results. For a service to pass the tag filter it must have *all* 231 of the required tags, and *none* of the excluded tags (prefixed with `!`). 232 233 - `NodeMeta` `(map<string|string>: nil)` - Specifies a list of user-defined 234 key/value pairs that will be used for filtering the query results to nodes 235 with the given metadata values present. 236 237 - `Connect` `(bool: false)` - If true, only [Connect-capable](/docs/connect/index.html) services 238 for the specified service name will be returned. This includes both 239 natively integrated services and proxies. For proxies, the proxy name 240 may not match `Service`, because the proxy destination will. Any 241 constrains beyond the service name such as `Near`, `Tags`, and `NodeMeta` 242 are applied to Connect-capable service. 243 244- `DNS` `(DNS: nil)` - Specifies DNS configuration 245 246 - `TTL` `(string: "")` - Specifies the TTL duration when query results are 247 served over DNS. If this is specified, it will take precedence over any 248 Consul agent-specific configuration. 249 250### Sample Payload 251 252```json 253{ 254 "Name": "my-query", 255 "Session": "adf4238a-882b-9ddc-4a9d-5b6758e4159e", 256 "Token": "", 257 "Service": { 258 "Service": "redis", 259 "Failover": { 260 "NearestN": 3, 261 "Datacenters": ["dc1", "dc2"] 262 }, 263 "Near": "node1", 264 "OnlyPassing": false, 265 "Tags": ["primary", "!experimental"], 266 "NodeMeta": {"instance_type": "m3.large"} 267 }, 268 "DNS": { 269 "TTL": "10s" 270 } 271} 272``` 273 274### Sample Request 275 276```text 277$ curl \ 278 --request POST \ 279 --data @payload.json \ 280 http://127.0.0.1:8500/v1/query 281``` 282 283### Sample Response 284 285```json 286{ 287 "ID": "8f246b77-f3e1-ff88-5b48-8ec93abf3e05" 288} 289``` 290 291## Read Prepared Query 292 293This endpoint returns a list of all prepared queries. 294 295| Method | Path | Produces | 296| ------ | ---------------------------- | -------------------------- | 297| `GET` | `/query` | `application/json` | 298 299The table below shows this endpoint's support for 300[blocking queries](/api/index.html#blocking-queries), 301[consistency modes](/api/index.html#consistency-modes), 302[agent caching](/api/index.html#agent-caching), and 303[required ACLs](/api/index.html#acls). 304 305| Blocking Queries | Consistency Modes | Agent Caching | ACL Required | 306| ---------------- | ----------------- | ------------- | ------------ | 307| `NO` | `none` | `none` | `query:read` | 308 309### Parameters 310 311- `dc` `(string: "")` - Specifies the datacenter to query. This will default to 312 the datacenter of the agent being queried. This is specified as part of the 313 URL as a query parameter. 314 315### Sample Request 316 317```text 318$ curl \ 319 http://127.0.0.1:8500/v1/query 320``` 321 322### Sample Response 323 324```json 325[ 326 { 327 "ID": "8f246b77-f3e1-ff88-5b48-8ec93abf3e05", 328 "Name": "my-query", 329 "Session": "adf4238a-882b-9ddc-4a9d-5b6758e4159e", 330 "Token": "<hidden>", 331 "Service": { 332 "Service": "redis", 333 "Failover": { 334 "NearestN": 3, 335 "Datacenters": ["dc1", "dc2"] 336 }, 337 "OnlyPassing": false, 338 "Tags": ["primary", "!experimental"], 339 "NodeMeta": {"instance_type": "m3.large"} 340 }, 341 "DNS": { 342 "TTL": "10s" 343 }, 344 "RaftIndex": { 345 "CreateIndex": 23, 346 "ModifyIndex": 42 347 } 348 } 349] 350``` 351 352### Update Prepared Query 353 354This endpoint updates an existing prepared query. If no query exists by the 355given ID, an error is returned. 356 357| Method | Path | Produces | 358| ------ | ---------------------------- | -------------------------- | 359| `PUT` | `/query/:uuid` | `application/json` | 360 361The table below shows this endpoint's support for 362[blocking queries](/api/index.html#blocking-queries), 363[consistency modes](/api/index.html#consistency-modes), 364[agent caching](/api/index.html#agent-caching), and 365[required ACLs](/api/index.html#acls). 366 367| Blocking Queries | Consistency Modes | Agent Caching | ACL Required | 368| ---------------- | ----------------- | ------------- | ------------- | 369| `NO` | `none` | `none` | `query:write` | 370 371### Parameters 372 373- `uuid` `(string: <required>)` - Specifies the UUID of the query to update. 374 This is required and is specified as part of the URL path. 375 376- `dc` `(string: "")` - Specifies the datacenter to query. This will default to 377 the datacenter of the agent being queried. This is specified as part of the 378 URL as a query parameter. 379 380The body is the same as is used to create a prepared query. Please see above for 381more information. 382 383### Sample Request 384 385```text 386$ curl \ 387 --request PUT \ 388 --data @payload.json \ 389 http://127.0.0.1:8500/v1/query/8f246b77-f3e1-ff88-5b48-8ec93abf3e05 390``` 391 392## Read Prepared Query 393 394This endpoint reads an existing prepared query. If no query exists by the 395given ID, an error is returned. 396 397| Method | Path | Produces | 398| ------ | ---------------------------- | -------------------------- | 399| `GET` | `/query/:uuid` | `application/json` | 400 401The table below shows this endpoint's support for 402[blocking queries](/api/index.html#blocking-queries), 403[consistency modes](/api/index.html#consistency-modes), 404[agent caching](/api/index.html#agent-caching), and 405[required ACLs](/api/index.html#acls). 406 407| Blocking Queries | Consistency Modes | Agent Caching | ACL Required | 408| ---------------- | ----------------- | ------------- | ------------ | 409| `NO` | `none` | `none` | `query:read` | 410 411### Parameters 412 413- `uuid` `(string: <required>)` - Specifies the UUID of the query to read. 414 This is required and is specified as part of the URL path. 415 416- `dc` `(string: "")` - Specifies the datacenter to query. This will default to 417 the datacenter of the agent being queried. This is specified as part of the 418 URL as a query parameter. 419 420### Sample Request 421 422```text 423$ curl \ 424 http://127.0.0.1:8500/v1/query/8f246b77-f3e1-ff88-5b48-8ec93abf3e05 425``` 426 427### Sample Response 428 429The returned response is the same as the list of prepared queries above, only 430with a single item present. 431 432## Delete Prepared Query 433 434This endpoint deletes an existing prepared query. If no query exists by the 435given ID, an error is returned. 436 437| Method | Path | Produces | 438| --------- | ---------------------------- | -------------------------- | 439| `DELETE` | `/query/:uuid` | `application/json` | 440 441The table below shows this endpoint's support for 442[blocking queries](/api/index.html#blocking-queries), 443[consistency modes](/api/index.html#consistency-modes), 444[agent caching](/api/index.html#agent-caching), and 445[required ACLs](/api/index.html#acls). 446 447| Blocking Queries | Consistency Modes | Agent Caching | ACL Required | 448| ---------------- | ----------------- | ------------- | ------------- | 449| `NO` | `none` | `none` | `query:write` | 450 451### Parameters 452 453- `uuid` `(string: <required>)` - Specifies the UUID of the query to delete. 454 This is required and is specified as part of the URL path. 455 456- `dc` `(string: "")` - Specifies the datacenter to query. This will default to 457 the datacenter of the agent being queried. This is specified as part of the 458 URL as a query parameter. 459 460### Sample Request 461 462```text 463$ curl \ 464 --request DELETE \ 465 http://127.0.0.1:8500/v1/query/8f246b77-f3e1-ff88-5b48-8ec93abf3e05 466``` 467 468## Execute Prepared Query 469 470This endpoint executes an existing prepared query. If no query exists by the 471given ID, an error is returned. 472 473| Method | Path | Produces | 474| ------ | ---------------------------- | -------------------------- | 475| `GET` | `/query/:uuid/execute` | `application/json` | 476 477The table below shows this endpoint's support for 478[blocking queries](/api/index.html#blocking-queries), 479[consistency modes](/api/index.html#consistency-modes), 480[agent caching](/api/index.html#agent-caching), and 481[required ACLs](/api/index.html#acls). 482 483| Blocking Queries | Consistency Modes | Agent Caching | ACL Required | 484| ---------------- | ----------------- | ------------- | ------------ | 485| `NO` | `none` | `simple` | `depends`<sup>1</sup> | 486 487<sup>1</sup> If an ACL Token was bound to the query when it was defined then it 488will be used when executing the request. Otherwise, the client's supplied ACL 489Token will be used. 490 491### Parameters 492 493- `uuid` `(string: <required>)` - Specifies the UUID of the query to execute. 494 This is required and is specified as part of the URL path. This can also be 495 the name of an existing prepared query, or a name that matches a prefix name 496 for a prepared query template. 497 498- `dc` `(string: "")` - Specifies the datacenter to query. This will default to 499 the datacenter of the agent being queried. This is specified as part of the 500 URL as a query parameter. 501 502- `near` `(string: "")` - Specifies to sort the resulting list in ascending 503 order based on the estimated round trip time from that node. Passing 504 `?near=_agent` will use the agent's node for the sort. Passing `?near=_ip` 505 will use the source IP of the request or the value of the X-Forwarded-For 506 header to lookup the node to use for the sort. If this is not present, 507 the default behavior will shuffle the nodes randomly each time the query is 508 executed. 509 510- `limit` `(int: 0)` - Limit the size of the list to the given number of nodes. 511 This is applied after any sorting or shuffling. 512 513- `connect` `(bool: false)` - If true, limit results to nodes that are 514 Connect-capable only. This can also be specified directly on the template 515 itself to force all executions of a query to be Connect-only. See the 516 template documentation for more information. 517 518### Sample Request 519 520```text 521$ curl \ 522 http://127.0.0.1:8500/v1/query/8f246b77-f3e1-ff88-5b48-8ec93abf3e05/execute?near=_agent 523``` 524 525### Sample Response 526 527```json 528{ 529 "Service": "redis", 530 "Nodes": [ 531 { 532 "Node": { 533 "ID": "40e4a748-2192-161a-0510-9bf59fe950b5", 534 "Node": "foobar", 535 "Address": "10.1.10.12", 536 "Datacenter": "dc1", 537 "TaggedAddresses": { 538 "lan": "10.1.10.12", 539 "wan": "10.1.10.12" 540 }, 541 "NodeMeta": {"instance_type": "m3.large"} 542 }, 543 "Service": { 544 "ID": "redis", 545 "Service": "redis", 546 "Tags": null, 547 "Meta": {"redis_version": "4.0"}, 548 "Port": 8000 549 }, 550 "Checks": [ 551 { 552 "Node": "foobar", 553 "CheckID": "service:redis", 554 "Name": "Service 'redis' check", 555 "Status": "passing", 556 "Notes": "", 557 "Output": "", 558 "ServiceID": "redis", 559 "ServiceName": "redis" 560 }, 561 { 562 "Node": "foobar", 563 "CheckID": "serfHealth", 564 "Name": "Serf Health Status", 565 "Status": "passing", 566 "Notes": "", 567 "Output": "", 568 "ServiceID": "", 569 "ServiceName": "" 570 } 571 ], 572 "DNS": { 573 "TTL": "10s" 574 }, 575 "Datacenter": "dc3", 576 "Failovers": 2 577 }] 578} 579``` 580 581- `Nodes` contains the list of healthy nodes providing the given service, as 582 specified by the constraints of the prepared query. 583 584- `Service` has the service name that the query was selecting. This is useful 585 for context in case an empty list of nodes is returned. 586 587- `DNS` has information used when serving the results over DNS. This is just a 588 copy of the structure given when the prepared query was created. 589 590- `Datacenter` has the datacenter that ultimately provided the list of nodes and 591 `Failovers` has the number of remote datacenters that were queried while 592 executing the query. This provides some insight into where the data came from. 593 This will be zero during non-failover operations where there were healthy 594 nodes found in the local datacenter. 595 596## Explain Prepared Query 597 598This endpoint generates a fully-rendered query for a given name, post 599interpolation. 600 601| Method | Path | Produces | 602| ------ | ---------------------------- | -------------------------- | 603| `GET` | `/query/:uuid/explain` | `application/json` | 604 605The table below shows this endpoint's support for 606[blocking queries](/api/index.html#blocking-queries), 607[consistency modes](/api/index.html#consistency-modes), 608[agent caching](/api/index.html#agent-caching), and 609[required ACLs](/api/index.html#acls). 610 611| Blocking Queries | Consistency Modes | Agent Caching | ACL Required | 612| ---------------- | ----------------- | ------------- | ------------ | 613| `NO` | `none` | `none` | `query:read` | 614 615### Parameters 616 617- `uuid` `(string: <required>)` - Specifies the UUID of the query to explain. 618 This is required and is specified as part of the URL path. This can also be 619 the name of an existing prepared query, or a name that matches a prefix name 620 for a prepared query template. 621 622- `dc` `(string: "")` - Specifies the datacenter to query. This will default to 623 the datacenter of the agent being queried. This is specified as part of the 624 URL as a query parameter. 625 626### Sample Request 627 628```text 629$ curl \ 630 http://127.0.0.1:8500/v1/query/8f246b77-f3e1-ff88-5b48-8ec93abf3e05/explain 631``` 632 633### Sample Response 634 635```json 636{ 637 "Query": { 638 "ID": "8f246b77-f3e1-ff88-5b48-8ec93abf3e05", 639 "Name": "my-query", 640 "Session": "adf4238a-882b-9ddc-4a9d-5b6758e4159e", 641 "Token": "<hidden>", 642 "Name": "geo-db", 643 "Template": { 644 "Type": "name_prefix_match", 645 "Regexp": "^geo-db-(.*?)-([^\\-]+?)$" 646 }, 647 "Service": { 648 "Service": "mysql-customer", 649 "Failover": { 650 "NearestN": 3, 651 "Datacenters": ["dc1", "dc2"] 652 }, 653 "OnlyPassing": true, 654 "Tags": ["primary"], 655 "Meta": { "mysql_version": "5.7.20" }, 656 "NodeMeta": {"instance_type": "m3.large"} 657 } 658 } 659} 660``` 661