Readyset Docs

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

ImageComponentBinary
querypilotRouterquerypilot
querypilot-acceleratorStandalone Acceleratorquerypilot-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

ServicePortProtocolNotes
Router, PostgreSQL wire5433PostgreSQLApplications connect here
Router, metrics9090HTTP (Prometheus)sqp_* series
Router, admin API9091HTTPAlways 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:latest

Getting 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-stopped
QUERYPILOT_IMAGE=readysettech/querypilot:latest docker compose up -d

Connect.

psql -h localhost -p 5433 -U <pool-user> -d <database>

Stop.

docker compose down

Post-deploy validation

Work through this checklist after any deployment.

  1. Router is healthy. curl -sf http://localhost:9091/api/config/status returns 200 with the live config path.
  2. Traffic flows. Run a query through port 5433, then confirm sqp_queries_total appears and increments in curl http://localhost:9090/metrics. See the metrics reference.
  3. Routing is what you intended. curl "http://localhost:9091/api/routing/test?sql=SELECT%20count(*)%20FROM%20your_table" returns the expected target_pool.

Day-2 concerns (reload, shutdown, monitoring) are covered in Operations; the shipped Grafana dashboard and alert rules are in QueryPilot Optional Configurations.