Reset a seeded environment
Seeding is slow. Do it once, snapshot, and reset from the snapshot for the rest of the project's life.
Runs against the demo project.
1. Seed everything, once
docker compose exec -T postgres psql -U postgres -d demo <<'SQL'
CREATE TABLE tenants (id serial PRIMARY KEY, name text NOT NULL);
CREATE TABLE orders (id serial PRIMARY KEY, tenant_id int REFERENCES tenants(id), total numeric);
INSERT INTO tenants (name) VALUES ('acme'), ('globex'), ('initech');
INSERT INTO orders (tenant_id, total) SELECT (n % 3) + 1, n * 1.5 FROM generate_series(1, 5000) n;
SQL
docker compose exec -T minio sh -c '
mkdir -p /data/demo/invoices
for i in 1 2 3; do echo "invoice $i" > /data/demo/invoices/inv-$i.txt; done
'
docker compose exec -T redis redis-cli MSET \
tenants:count 3 orders:count 5000 cache:warmed 1
2. Capture the baseline
arcave savepoint create clean --description "seeded baseline — do not delete"
{
"id": "019e83ff-30c0-7000-8000-000000000000",
"name": "clean",
"description": "seeded baseline — do not delete",
"created_at": "2026-06-01T18:36:40.002114Z",
"stats": [
{ "volume": { "object_id": "volume-named-arcave-demo_pgdata", "type": "named", "backend": "fullcopy" }, "type": "fullcopy" },
{ "volume": { "object_id": "volume-named-arcave-demo_miniodata", "type": "named", "backend": "fullcopy" }, "type": "fullcopy" },
{ "volume": { "object_id": "volume-anon-redis-1-data", "type": "anon", "backend": "fullcopy" }, "type": "fullcopy" }
],
"writable_layers": [
{ "service": "minio", "replica": 1, "container_name": "arcave-demo-minio-1", "upstream_image_ref": "minio/minio:latest" },
{ "service": "postgres", "replica": 1, "container_name": "arcave-demo-postgres-1", "upstream_image_ref": "postgres:16" },
{ "service": "redis", "replica": 1, "container_name": "arcave-demo-redis-1", "upstream_image_ref": "redis:7" }
],
"images": [
{ "id": "sha256:…", "refs": ["minio/minio:latest"], "stored": true },
{ "id": "sha256:…", "refs": ["postgres:16"], "stored": true },
{ "id": "sha256:…", "refs": ["redis:7"], "stored": true }
],
"spec": { "format": "compose-yaml" }
}
Trimmed to the fields that identify each entry; Roll back a failed migration shows one of each in full. Three volumes, three writable layers, three images, one savepoint.
3. Let a test suite make a mess
docker compose exec -T postgres psql -U postgres -d demo -c 'TRUNCATE orders CASCADE;'
docker compose exec -T minio sh -c 'rm -rf /data/demo/invoices'
docker compose exec -T redis redis-cli FLUSHALL
4. Reset
arcave rollback clean
5. Verify all three came back
docker compose exec -T postgres psql -U postgres -d demo -tAc 'SELECT count(*) FROM orders;'
5000
docker compose exec -T minio sh -c 'ls /data/demo/invoices'
inv-1.txt
inv-2.txt
inv-3.txt
docker compose exec -T redis redis-cli MGET tenants:count orders:count cache:warmed
1) "3"
2) "5000"
3) "1"
This is the point of whole-project capture. A pg_restore would have given you the first of those three, and left the object store empty and the cache cold.
6. Wire it into the test suite
#!/usr/bin/env bash
set -euo pipefail
export ARCAVE_PROJECT_NAME=arcave-demo
arcave rollback clean # reset BEFORE, not after
./integration-tests.sh
Resetting before rather than after has two advantages: a crashed suite cannot skip its own cleanup, and you can inspect the wreckage of a failed run before the next one wipes it.
7. Protect the baseline
arcave savepoint list
[
{ "id": "019e8488-3ac8-7000-8000-000000000000", "name": "after-refactor", "description": "", "created_at": "2026-06-01T21:13:01.114872Z" },
{ "id": "019e83ff-30c0-7000-8000-000000000000", "name": "clean", "description": "seeded baseline — do not delete", "created_at": "2026-06-01T18:36:40.002114Z" }
]
arcave savepoint remove --retain-recent 5 will delete clean once five newer savepoints exist. Retention rules do not know which savepoint is precious.
Prune by id instead:
arcave savepoint remove 019e8488-3ac8-7000-8000-000000000000
Or keep the baseline in a session of its own. Retention works within one session, so no sweep in the session you work in can reach it:
arcave session create --name fixtures
arcave --session fixtures savepoint create clean --description "seeded baseline — do not delete"
arcave --session fixtures rollback clean
./integration-tests.sh
Take the savepoint right after seeding, as in step 2. The commands that name no session keep working in yours, and arcave savepoint remove --retain-recent 5 there never sees clean.
Related docs
- Resetting fixtures and demos — the pattern.
- Prune savepoints with retention rules — the next example.
- savepoint remove — the retention rules in full.