Deployment modes¶
One worker binary, two ways to run it. Both coordinate through the tierdb.* catalog and campaign for the same leader lease, so they coexist freely: exactly one worker leads at a time, the rest stand by.
External workers (the default)¶
The daemon runs as its own service, wherever you run services (VM, k8s, ECS, ...), configured entirely through TIERDB_* env vars pointing at your Postgres and object store:
TIERDB_PG_URL='jdbc:postgresql://db.internal:5432/app?sslmode=verify-full'
TIERDB_PG_USER=tierdb_worker
TIERDB_WAREHOUSE=s3://analytics-lake/tierdb
java -jar tierdb-worker.jar run
This is the disaggregated topology: the data-moving half scales, restarts, and upgrades on its own schedule, without touching the database. Run at least two instances; they fail over automatically through the leader lease, including the mirrored tables' replication slots. And because the worker is just a JDBC client, it runs against managed Postgres (RDS, Cloud SQL) where extensions are forbidden, with reads served through connectors.
Production deployment documents this mode end to end: roles, encryption, WAL safety, upgrades.
Embedded worker¶
The extension registers a Postgres background worker that launches and supervises the same daemon as a child process. One Postgres instance with the extension installed is a fully working TierDB, web console included; there is no second service to deploy, monitor, or restart.
The supervisor starts the daemon after recovery finishes (never on a hot standby), restarts it if it exits, forwards Postgres shutdown to it, and sends its output to the Postgres server log. After a failover, the promoted primary starts its own.
No Java install is needed: releases ship a tierdb-embedded bundle, the console jar plus a trimmed self-contained runtime. Unpack it to /opt/tierdb and the supervisor finds it there by default.
Choosing¶
- Production fleets and anything that should scale or upgrade independently of the database: external.
- Managed Postgres where you cannot install extensions: external, it is the only option.
- Development machines, demos, small single-instance deployments, hosting platforms where you control the Postgres image but not a fleet: embedded.
- Mixed: enabling embedded next to an external fleet is safe. The lease arbitrates, and the embedded worker simply stands by unless it wins.
Running embedded¶
shared_preload_libraries = 'pg_duckdb, tierdb'
tierdb.embedded_worker = on
Both need a Postgres restart. If the GUC is on but the library is not preloaded, startup logs a warning and nothing runs.
| GUC | Default | Meaning |
|---|---|---|
tierdb.embedded_worker |
off |
Register the supervisor background worker. |
tierdb.worker_command |
unset | Command line to run. Unset, the bundle under /opt/tierdb is used when present. |
tierdb.worker_database |
postgres |
Database the daemon connects to. |
tierdb.worker_env |
unset | Extra environment as key=value;key=value. |
The daemon reads the same TIERDB_* env vars as an external worker. It inherits the postmaster's environment, the supervisor sets TIERDB_PG_URL to this instance, and tierdb.worker_env entries are applied last and win:
tierdb.worker_env = 'TIERDB_PG_USER=tierdb_worker;TIERDB_WAREHOUSE=s3://lake/tierdb'
A custom command replaces the bundled default:
tierdb.worker_command = 'java -jar /path/to/tierdb-console.jar run'
The repository ships a compose overlay that runs the example stack embedded, with no worker container:
EXAMPLE_EMBEDDED=1 make -C example up
EXAMPLE_EMBEDDED=1 make -C example scenarios