Plain PostgreSQL Deployment¶
Audience: Administrators deploying Sentari without TimescaleDB
Sentari uses TimescaleDB by default because it provides time-series partitioning for scan history at scale. However, TimescaleDB is optional. Plain PostgreSQL 16 is fully supported, and the application auto-detects which database is available at migration time.
Compatibility¶
| Requirement | Detail |
|---|---|
| Minimum version | PostgreSQL 16 |
| Recommended | TimescaleDB 2.14 on PostgreSQL 16 |
| Auto-detection | The migration checks for the TimescaleDB extension at startup. No configuration is required — the application adapts automatically. |
| Existing data | You can switch from PostgreSQL to TimescaleDB later without a data migration (see Adding TimescaleDB later). |
Docker Compose¶
Change the db service image in the docker-compose.yml from your bundle:
db:
image: postgres:16-alpine # replaces timescale/timescaledb:2.14.2-pg16
environment:
POSTGRES_DB: sentari
POSTGRES_USER: sentari
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
ports:
- "127.0.0.1:5432:5432"
volumes:
- db-data:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U sentari"]
interval: 5s
timeout: 5s
retries: 5
restart: unless-stopped
No other changes are required. The connection URL, environment variables, and all other services remain identical.
Start the stack:
docker compose up -d
Helm (Kubernetes)¶
Option A: Override the bundled database image¶
If Sentari manages the database as a StatefulSet inside your cluster, override
the database image. Add these keys to your own overrides file (the chart does not
ship a values-postgres.yaml):
# my-overrides.yaml — author this alongside your secrets/config
database:
image:
registry: docker.io
repository: postgres
tag: "16-alpine"
Apply at install time, supplying secrets either inline via --set, in the same
overrides file, or through a pre-created Secret referenced with
secrets.existingSecretName:
helm install sentari deploy/helm/sentari/ \
--namespace sentari \
-f my-overrides.yaml \
--set secrets.existingSecretName=sentari-credentials
Option B: External managed PostgreSQL¶
Use this when you have an existing managed PostgreSQL service (on-premises, RDS, Azure Database for PostgreSQL, etc.):
helm install sentari deploy/helm/sentari/ \
--namespace sentari \
--set database.external=true \
--set secrets.databaseUrl="postgresql+psycopg2://sentari:<password>@<host>:5432/sentari" \
--set secrets.secretKey="<jwt-signing-key>" \
--set secrets.enrollmentToken="<token>" \
--set secrets.bootstrapAdminEmail="admin@yourorganisation.com" \
--set secrets.bootstrapAdminPassword="<password>" \
--set redis.external=true \
--set secrets.redisUrl="redis://:<password>@<host>:6379/0"
When database.external=true, the chart does not deploy a database StatefulSet.
You are responsible for ensuring the database is accessible from the Sentari namespace
and that the sentari database and user exist before deployment.
Create the database and user if not already present:
CREATE USER sentari WITH PASSWORD '<password>';
CREATE DATABASE sentari OWNER sentari;
What you lose without TimescaleDB¶
| Feature | With TimescaleDB | Without TimescaleDB |
|---|---|---|
| Automatic time-based partitioning | Yes — scan_results is a hypertable |
No — single table, full sequential scan on large ranges |
| Time-range query performance | Partition pruning; fast on any fleet size | Acceptable up to ~200 devices / 3 months; degrades beyond that |
time_bucket() aggregates |
Available | Not available — the application uses date_trunc() which works on both |
| Automatic data retention policies | Configurable chunk-level retention | Requires manual DELETE or partitioning setup |
| Compression | Automatic chunk compression | Not available |
The application falls back to date_trunc() for all time-bucketed queries when
TimescaleDB is absent, so all dashboard features remain functional. Performance at
scale is the primary trade-off.
When to add TimescaleDB¶
Consider switching to TimescaleDB when any of the following apply:
- More than 200 devices submitting scans
- More than 3 months of scan history retained
- Time-range queries on the Scan History page are noticeably slow (over 5 seconds)
- You require data retention policies or automatic compression
Adding TimescaleDB to an existing deployment¶
TimescaleDB is a PostgreSQL extension installed alongside PostgreSQL. It does not require a separate database server and can be added to an existing Sentari database without migrating data:
- Replace the PostgreSQL container with the TimescaleDB image (same PostgreSQL major version):
# Stop the current database container
docker compose stop db
# Edit docker-compose.yml: change the db image back to timescale/timescaledb:2.14.2-pg16
# The existing volume (db-data) is reused — no data loss.
docker compose up -d db
- Enable the extension in the existing database:
docker compose exec db psql -U sentari -d sentari -c "CREATE EXTENSION IF NOT EXISTS timescaledb;"
- Run Alembic migrations to convert
scan_resultsto a hypertable:
docker compose exec sentari-api alembic upgrade head
The migration uses a DO $$ ... $$ guard that only creates the hypertable when
the extension is present. Running it against an existing PostgreSQL database
(without TimescaleDB) is safe — the guard skips the hypertable step.
- Verify:
docker compose exec db psql -U sentari -d sentari \
-c "SELECT hypertable_name FROM timescaledb_information.hypertables;"
# Expected: scan_results
For additional assistance, contact your Sentari representative or visit the support portal.