Upgrade, backup, and restore

Upgrade Netstamp safely, back up PostgreSQL, restore a deployment, and understand the admin JSON export.

Netstamp applies forward database migrations before the controller starts. Treat the application image and database schema as one release unit.

Before an upgrade

  1. Record the current NETSTAMP_VERSION and TIMESCALEDB_IMAGE values.
  2. Read the changes between the current and target revisions.
  3. Create a PostgreSQL backup.
  4. Verify that the backup can be read.
  5. Schedule a maintenance window when the change is operationally significant.

Netstamp’s columnstore policies require TimescaleDB 2.20.3 or newer. The extension version stored in an existing database does not update merely because the container image changes. Check it before running Netstamp migrations:

sql
SELECT extversion
FROM pg_extension
WHERE extname = 'timescaledb';

Create a database backup

Use PostgreSQL’s custom archive format:

bash
backup_file="netstamp-$(date -u +%Y%m%dT%H%M%SZ).dump"
docker compose exec -T postgres \
pg_dump -U netstamp -d netstamp --format=custom > "$backup_file"
pg_restore --list "$backup_file" >/dev/null

Store the dump together with the Compose files, the non-secret version settings, and an encrypted copy of the stable secret material needed to interpret credentials and stored settings.

Upgrade

Edit .env to select tested Netstamp and TimescaleDB versions. After creating the backup, update the database container and the installed extension before running Netstamp migrations:

bash
docker compose pull postgres
docker compose up -d postgres
docker compose exec -T postgres \
psql -X -U netstamp -d netstamp -c 'ALTER EXTENSION timescaledb UPDATE;'
docker compose pull
docker compose up -d
docker compose ps
docker compose logs migrate
docker compose logs --tail=200 netstamp

The migration container must exit successfully before the controller starts. Verify health, sign-in, one result query, one probe heartbeat, and one public status page.

Monitor columnstore policies

Netstamp leaves recent result chunks in rowstore and converts older chunks in the background. Raw result chunks become eligible after one day; permanent one-minute rollups and traceroute samples become eligible after seven days. The first policy runs are staggered across the first 90 minutes after migration.

Check the configured layout and scheduled jobs:

sql
SELECT hypertable, segmentby, orderby
FROM timescaledb_information.hypertable_columnstore_settings
ORDER BY hypertable;

SELECT job_id, hypertable_name, schedule_interval, next_start, config
FROM timescaledb_information.jobs
WHERE proc_name = 'policy_compression'
ORDER BY next_start;

Check conversion statistics and recent failures:

sql
SELECT * FROM hypertable_columnstore_stats('ping_results');

SELECT job_id, start_time, sqlerrcode, err_message
FROM timescaledb_information.job_errors
WHERE proc_name = 'policy_compression'
ORDER BY start_time DESC;

A failed policy does not remove data: eligible chunks remain in rowstore and the job is retried by TimescaleDB. A Goose down migration removes the policies but intentionally leaves already converted chunks in columnstore. Use the pre-upgrade backup when a complete physical rollback to rowstore is required.

Restore a backup

Restore into a new database or a disposable environment first whenever possible. For an in-place restore:

bash
docker compose stop netstamp
docker compose exec -T postgres \
pg_restore -U netstamp -d netstamp --clean --if-exists --no-owner < netstamp-backup.dump
docker compose run --rm migrate
docker compose up -d netstamp

Then verify:

bash
docker compose ps
curl --fail http://127.0.0.1:3000/api/v1/healthz

If the backup came from another installation, restore the matching SYSTEM_SETTINGS_ENCRYPTION_KEY. Session and API-token hash keys must also match if existing sessions and tokens are expected to remain valid.

Admin JSON export and import

System administrators can download and import a Netstamp JSON data package from Admin → Data. It is useful for application-level portability and controlled administrative workflows.

It is not a substitute for a PostgreSQL backup because it does not preserve database-level metadata, extensions, ownership, or an exact point-in-time recovery boundary. Use pg_dump for disaster recovery and test the admin package separately if it is part of your migration plan.

Database volume safety

These commands have different effects:

bash
docker compose down        # removes containers and network; keeps the database volume
docker compose down -v     # also deletes the database volume

Never add -v to routine stop, restart, or upgrade procedures.