Getting started

Installation

Run StreamQL as a container, on Kubernetes, with Helm, or as a systemd service.

Requirements#

  • A PostgreSQL server, version 13 through 19. It can be self-managed or a managed service.
  • A role StreamQL can log in with. Its credentials are given as the upstream URL.
  • For slow-query insights, a monitoring role with pg_read_all_stats and pg_stat_statements in shared_preload_libraries.

Choose an edition#

StreamQL comes in two editions. They share the same pooling engine, so you can start with one and move to the other.

Full featured (default)Pool only
What it isThe default binary and imagePooling without the web UI
Web consoleyesno
Admin API, /metrics, /livez, /readyzyesno (the admin port is not bound)
Alerts, query insights, MCP access, fleetyesno
Pooling modes, session-state safety, prepared statementsyesyes
Client TLS, upstream TLS, SCRAM, MD5, auth_queryyesyes
Limits, queue deadlines, reserve pools, hot reload by SIGHUPyesyes

Run the full edition#

The default build and the image ghcr.io/streamql/streamql include everything: the console and admin API on the admin port (9930), alerts, slow-query insights and the fleet control plane.

docker run, full
docker run --rm -p 6432:6432 -p 127.0.0.1:9930:9930 \
  -e STREAMQL_UPSTREAM__URL='postgres://app:APP_PASSWORD@db.example.com:5432/app?sslmode=require' \
  ghcr.io/streamql/streamql:latest

Run pool only#

Pool only is for places where you want just a pooler: no web UI, no admin listener and no insights pass. There are two ways to get it.

1. Switch it off at run time on the normal binary or image. With admin.enabled = false (or --no-admin) the admin port is not bound at all, so the console, the admin API and /metrics are gone. insights.enabled = false stops the statement fingerprint pass.

environment
STREAMQL_UPSTREAM__URL=file:/run/secrets/upstream_url
STREAMQL_ADMIN__ENABLED=false
STREAMQL_INSIGHTS__ENABLED=false
streamql.toml, pool only
[upstream]
url = "file:/run/secrets/upstream_url"

[admin]
enabled = false

[insights]
enabled = false

[defaults]
mode = "transaction"
max_size = 20
run-time switch
# binary
streamql --upstream postgres://app:APP_PASSWORD@db.example.com:5432/app --listen 0.0.0.0:6432 --no-admin

# container, same image as the full edition
docker run --rm -p 6432:6432 \
  -e STREAMQL_UPSTREAM__URL='postgres://app:APP_PASSWORD@db.example.com:5432/app?sslmode=require' \
  -e STREAMQL_ADMIN__ENABLED=false -e STREAMQL_INSIGHTS__ENABLED=false \
  ghcr.io/streamql/streamql:latest

2. Use the pool-only build, which does not compile the web console in. It is built without the default features:

pool-only build
cargo build --release -p streamql --no-default-features --features mimalloc   # same as: make build-pool-only
docker build --build-arg CARGO_FEATURES="--no-default-features --features mimalloc" -t streamql:pool-only .   # same as: make image-pool-only
docker run, pool-only image
docker run --rm -p 6432:6432 \
  -e STREAMQL_UPSTREAM__URL='postgres://app:APP_PASSWORD@db.example.com:5432/app?sslmode=require' \
  -e STREAMQL_ADMIN__ENABLED=false \
  ghcr.io/streamql/streamql:latest-pool-only

The published pool-only image and archives are built this way. --no-default-features also leaves out the default secrets-vault feature, so Vault secret references are unavailable in that build. Add it back with --features mimalloc,secrets-vault if you need them.

What you give up in pool only#

  • The web console, the admin API under /api/v1, and the probes and metrics served by the admin listener: /livez, /readyz and /metrics. Use a TCP check on port 6432 for health checks instead of streamql probe against /readyz.
  • Alerts, slow-query insights, MCP access and the fleet management views.
  • Decision and trace evidence has nothing to read it with; you can switch recording off with STREAMQL_DATAPLANE__EVIDENCE=false.

What stays#

  • All three pooling modes, prepared statements across pooled backends, session-state tracking and replay, pinning, queue deadlines, limits, reserve pools and per-tenant shares.
  • Client TLS and upstream TLS, SCRAM-SHA-256, MD5 and auth_query.
  • Configuration from a file, environment variables and flags, validation with streamql config validate, and reload by SIGHUP.
  • Graceful drain on SIGTERM, and in-place binary upgrade with --upgrade.

Download a release#

The latest release is read from GitHub in your browser. Pick an edition to see the archives, packages and install commands for your platform. There is no Windows build: StreamQL targets Unix systems.

No release published yet

There is no packaged release to download yet. Build StreamQL from source, or watch the releases page.

shell
git clone https://github.com/streamql/streamql
cd streamql
cargo build --release -p streamql                                        # full featured
cargo build --release -p streamql --no-default-features --features mimalloc   # pool only

Release assets follow one naming scheme: streamql-<version>-<target>.tar.gz for the full edition, streamql-pool-only-<version>-<target>.tar.gz for pool only (Linux), streamql_<version>-1_<arch>.deb and streamql-<version>-1.<arch>.rpm, plus SHA256SUMS and a .sha256 file next to each download. Container images are ghcr.io/streamql/streamql:<version> and :<version>-pool-only, and latest and latest-pool-only follow the newest stable release. The version has no leading v: tag v0.1.0 is version 0.1.0.

Docker and Docker Compose#

deploy/docker/compose.yaml runs the gateway in front of your database. The image listens on port 6432 for PostgreSQL clients and on port 9930 for the console and API. It runs read-only with all capabilities dropped, and its health check is streamql probe http://127.0.0.1:9930/readyz.

deploy/docker
cd deploy/docker
mkdir -p secrets
printf 'postgres://app:APP_PASSWORD@db.example.com:5432/app?sslmode=require' > secrets/upstream_url
openssl rand -hex 24 > secrets/admin_token
docker compose up -d

Bring your own PostgreSQL#

  • Point upstream_url at any PostgreSQL 13 through 19 server. Use sslmode=verify-full and set STREAMQL_UPSTREAM__SSLROOTCERT (mount the CA file) for a server with a private CA.
  • A server on the Docker host is host.docker.internal on Docker Desktop and OrbStack. On Linux add extra_hosts: ["host.docker.internal:host-gateway"] to the service.
  • Without a server at hand, docker compose --profile demo up -d also starts a local PostgreSQL. Create secrets/postgres_password first.

Useful settings#

Every setting is an environment variable named STREAMQL_<SECTION>__<KEY>. Put them under environment: or in a .env file next to compose.yaml. A value written as file:/path is read from that file.

SettingDefaultMeaning
STREAMQL_DEFAULTS__MAX_SIZE20Server connections per database and role
STREAMQL_LIMITS__MAX_MESSAGE_BYTES268435456Largest message held whole in memory
STREAMQL_LIMITS__STREAM_LARGE_MESSAGEStrueRelay oversized row and COPY data in pieces
STREAMQL_UPSTREAM__READINESS_GRACE_S5How long the upstream may be unreachable before /readyz fails
STREAMQL_ACCESS__TRUSTED_PROXIESnoneCIDR list of reverse proxies whose X-Forwarded-For is believed
STREAMQL_MCP__ALLOWED_HOSTSloopback and the public console hostAccepted Host values of /mcp

Kubernetes with kustomize#

deploy/k8s contains a namespace, a StreamQL deployment and a demo PostgreSQL. Settings live in a generated ConfigMap, so editing a value changes the ConfigMap name and the pods roll.

deploy/k8s
kubectl apply -k deploy/k8s

The kustomization includes postgres.yaml, a demo database. Remove it from resources and set the upstream URL when you use your own server.

Helm#

The chart is in deploy/helm/streamql. By default it installs one gateway. Credentials can be passed as values or, better, read from existing Secrets.

helm
helm install streamql deploy/helm/streamql \
  --namespace streamql --create-namespace \
  --set gateway.upstream.url='postgres://app:APP_PASSWORD@db.example.com:5432/app' \
  --set gateway.admin.token="$(openssl rand -hex 24)"
ValueDefaultMeaning
gateway.replicaCount1Number of gateway pods
gateway.image.repositoryghcr.io/streamql/streamqlImage; the tag defaults to the chart appVersion
gateway.upstream.url / existingSecret / existingSecretKeyempty / empty / urlUpstream URL, or a Secret that holds it
gateway.admin.token / existingSecret / existingSecretKeyempty / empty / tokenAdmin bearer token, or a Secret that holds it
gateway.auth.existingSecret / keyempty / userlist.txtClient logins from a user list of "user" "SCRAM-SHA-256$..." lines
gateway.tls.existingSecretemptyA kubernetes.io/tls Secret for client TLS
gateway.envSTREAMQL_DEFAULTS__MAX_SIZE: "20", STREAMQL_LOG__FORMAT: jsonExtra STREAMQL_* settings
gateway.configemptyOptional TOML configuration; environment variables override it
gateway.drain.*preStopSeconds 5, endpointPropagationMs 2000, graceSeconds 30Graceful drain timings
gateway.service.*ClusterIP, port 6432, adminPort 9930Service type, ports, annotations, load balancer class and source ranges
gateway.pdb.*enabled, maxUnavailable 1Pod disruption budget
gateway.zoneSpread.*enabled, ScheduleAnywayTopology spread across zones
operator.enabledfalseInstall the operator with the Gateway, Pool and Policy resources

Platform values files are provided for OpenShift, EKS, AKS and GKE: values-openshift.yaml, values-eks.yaml, values-aks.yaml and values-gke.yaml. Matching kustomize overlays are in deploy/overlays.

Systemd#

packaging/systemd has streamql.service, streamql.socket, streamql-admin.socket and streamql-worker.service. The listen addresses come from the socket units, and sockets are passed to the process with socket activation, which also lets a new binary take over the listeners. packaging/streamql.toml is the starting configuration; every key can also be set as STREAMQL_<SECTION>__<KEY>, for example in /etc/streamql/streamql.env. Deb and rpm metadata is provided.

From source#

build
git clone https://github.com/streamql/streamql
cd streamql
cargo build --release          # binary in target/release/streamql
docker build -t streamql .     # container image
make image-pool-only           # pooling only, without the console

The image is a static, non-root image that runs without a shell. --no-admin turns the admin API and console off at run time.

Verify the install#

check
streamql config validate
curl -s http://127.0.0.1:9930/readyz