Deployment
Deploy QueryPilot with Docker or Docker Compose and validate the deployment afterwards.
QueryPilot ships as Docker images. Every deployment path on this page produces the same shape: the Router (binary querypilot) proxying client traffic between your applications and your database. Applications connect to the Router instead of the database directly. The database itself is external; none of these deployments run it for you.
MySQL support is in preview. MySQL proxying is functional, but PostgreSQL is the fully supported GA path. Where a deployment option below takes a MySQL backend, treat it as preview.
Images and registries
| Image | Component | Binary |
|---|---|---|
querypilot | Router | querypilot |
querypilot-accelerator | Standalone Accelerator | querypilot-accelerator |
Pre-release builds are published to public.ecr.aws/readyset with tags of the form X.Y.Z-<sha> (for example 0.1.0-72807f4e). Production releases are published to Docker Hub with X.Y.Z tags plus a moving latest. Published bits are the same images that passed the release gates; a pre-release tag is a build you can pull ahead of the corresponding production release.
The images are runtime-only: a non-root sqp user (UID/GID 999), the binary, curl for healthchecks, and nothing else. The Router image reads its config from QUERYPILOT_CONFIG=/etc/sqp/querypilot.toml, exposes 5433/9090/9091, and healthchecks itself with curl -sf http://localhost:9091/api/config/status (10s interval, 5s start period).
Port conventions
| Service | Port | Protocol | Notes |
|---|---|---|---|
| Router, PostgreSQL wire | 5433 | PostgreSQL | Applications connect here |
| Router, metrics | 9090 | HTTP (Prometheus) | sqp_* series |
| Router, admin API | 9091 | HTTP | Always metrics port + 1; not separately configurable |
The Router's admin API port is derived, not configured: it binds on the metrics IP at the metrics port + 1. The shipped healthchecks and validation tooling assume the 9090/9091 pair.
Single node with docker run
For a single-host deployment, run the image with a config mounted at /etc/sqp/querypilot.toml:
docker run -d --name querypilot --network host \
-v "$(pwd)/querypilot.toml:/etc/sqp/querypilot.toml:ro" \
readysettech/querypilot:latestGetting Started walks through this path end to end, including a minimal config and first proxied query.
Docker Compose
For a Compose-managed deployment against an external PostgreSQL reachable on localhost, use host networking so the config's 127.0.0.1 backend addresses work as-is. Treat the Compose file and config below as starting points you adapt, not turnkey production artifacts.
Write the Router config.
Save this as querypilot-router.toml next to your Compose file: one PostgreSQL listener on 0.0.0.0:5433 and a pool per role. Set each pool's username/password/database to your credentials; these also serve as the client-auth credentials (see Security).
[general]
pool_mode = "transaction"
[[listeners]]
protocol = "postgres"
bind = "0.0.0.0:5433"
[pools.primary]
role = "primary"
username = "<your_pg_user>"
password = "<your_pg_password>"
database = "<your_database>"
min_connections = 2
max_connections = 20
backends = [
{ host = "127.0.0.1", port = 5432 }
]
[pools.replica]
role = "replica"
username = "<your_pg_user>"
password = "<your_pg_password>"
database = "<your_database>"
min_connections = 2
max_connections = 50
backends = [
{ host = "<replica-host>", port = 5432 }
]
[routing]
read_write_split = true
read_pool = "replica"
write_pool = "primary"
default_pool = "primary"
# Pattern rules take priority over the read/write split; lower priority
# numbers win. Example: keep a hot query shape on the primary.
#[[routing.pattern_rules]]
#name = "orders_lookup_on_primary"
#type = "regex"
#pattern = "(?i)FROM orders WHERE order_id ="
#pool = "primary"
#priority = 10
[metrics]
enabled = true
bind = "0.0.0.0:9090"Single-backend deployments can drop the replica pool and the [routing] split; default_pool is all that is required. Every key is documented in the Router configuration reference.
Start the stack.
services:
querypilot:
image: ${QUERYPILOT_IMAGE:-readysettech/querypilot:latest}
network_mode: host
volumes:
- ./querypilot-router.toml:/etc/sqp/querypilot.toml:ro
restart: unless-stoppedQUERYPILOT_IMAGE=readysettech/querypilot:latest docker compose up -dConnect.
psql -h localhost -p 5433 -U <pool-user> -d <database>Stop.
docker compose downPost-deploy validation
Work through this checklist after any deployment.
- Router is healthy.
curl -sf http://localhost:9091/api/config/statusreturns 200 with the live config path. - Traffic flows. Run a query through port 5433, then confirm
sqp_queries_totalappears and increments incurl http://localhost:9090/metrics. See the metrics reference. - Routing is what you intended.
curl "http://localhost:9091/api/routing/test?sql=SELECT%20count(*)%20FROM%20your_table"returns the expectedtarget_pool.
Day-2 concerns (reload, shutdown, monitoring) are covered in Operations; the shipped Grafana dashboard and alert rules are in QueryPilot Optional Configurations.