Skip to content

Ask AI

Ask anything about Destesi — setup, products, APIs.

Powered by Claude. Answers may be wrong — always verify against the docs.

Concepts

Snap borrows git semantics for databases and object storage. You register a source once, then create as many isolated, writable branches from it as you like. This page covers the concepts; the reference covers the exact commands and fields.

A remote is your source — the production data you want to branch from. Like git remote add, you register it once and create many branches from it. Snap connects to the source read-only; it is never written to.

Supported kinds:

  • postgres — any PostgreSQL database (RDS, Supabase, Neon, self-hosted)
  • s3 — S3-compatible object storage (AWS S3, MinIO, Cloudflare R2)

When you register a remote, Snap verifies it can reach the source before saving it. A remote moves through these states:

  • pending — registered, verification in progress
  • healthy — reachable and ready to branch from
  • error — connection or verification failed
  • deleted — removed from the workspace

A branch is an isolated copy of a remote. Each branch has its own Postgres endpoint with full read/write access, and mutations never leak back to the source or to other branches.

You create a branch one of two ways:

  • clone — branch directly from a remote (like git clone), with --connector-id
  • fork — branch from an existing branch (like git checkout -b), with --from-snap. A fork inherits its parent’s remote.

A branch moves through these states:

  • pending / provisioning — the endpoint is being created
  • ready — the endpoint is live and the DSN is assigned
  • error — provisioning failed
  • expired — passed its time-to-live and was retired
  • deleted — removed and resources released

Snap uses copy-on-write semantics. Creating a branch copies no data — the branch reads through to the source the first time a table is touched, then snapshots that table into a private sandbox and serves every later query locally. Writes materialize the affected table first, then apply against the sandbox.

This gives you:

  • Instant creation — branches are ready in seconds regardless of source size
  • Minimal storage — you only store the data you actually touch
  • Full isolation — writes to one branch never affect the source or another branch

A branch is not limited to public. When Snap provisions a branch it discovers every user schema in the source — public plus anything else you created — and branches them all, skipping only Postgres’ own catalogs and Snap’s internal bookkeeping schemas. Each source schema gets its own private holding area inside the branch, so two tables that share a name in different schemas never collide.

Copy-on-write works the same way in every schema: billing.invoices reads through to the source on first touch and materializes into the sandbox exactly like a public table would.

One thing to know when you write SQL against a branch: Snap reads your statements to decide which table to materialize, and it treats an unqualified table name as living in public. Setting search_path alone is not enough to reach a table in another schema — qualify it (billing.invoices) so Snap resolves it correctly. Snap also refuses any statement that touches its internal _snap_* schemas, including a search_path that names one.

A checkpoint is a point-in-time reference for a remote, with a measured sync lag. When you create a branch you can pin it to a specific checkpoint with --at-checkpoint, or set a freshness bound with --max-lag so the branch is refused if the remote has fallen too far behind.

A fixture is a named, pinned branch that captures a known-good state — for example demo-data-q4 or post-incident-2026-05-03. Fixtures survive ad-hoc branch deletion, so you can keep a canonical starting point and fork fresh branches from it on demand.

Pin a ready branch as a fixture, then restore (fork) new branches from it:

Terminal window
dst snap fixture save snap_e5f6g7h8 --name demo-data-q4
dst snap fixture restore demo-data-q4 --as agent/run-42

A branch that is pinned by a fixture cannot be deleted until the fixture is removed first — the fixture is the durable handle.

Override rules rewrite specific columns as rows are copied from the source into a branch. Use them to mask PII (redirect every email to your own inbox), flip feature flags off, or restrict the snapshot to a single tenant with a where predicate.

Rules are attached when you create a branch and baked in once. Overridden tables hydrate synchronously, so a client never sees raw source data before the masks apply. Rules are immutable after creation — to change them, branch again with new rules.

Terminal window
# Mask emails and disable admin flags while branching
dst snap create agent/safe \
--connector-id conn_a1b2c3d4 \
--override "users.email='me@example.com'" \
--override users.is_admin=false

Configure rules via the CLI (--override, --overrides-file), the REST API (overrides on POST /v1/snaps), or the MCP tools.

Long-running actions — creating a branch, restoring a fixture — return an operation ID you can poll until it reaches a terminal state (completed or failed). The CLI and MCP tools poll automatically and block until the branch is ready.

Because a branch is a real Postgres endpoint, Snap exposes inspection and rollback as SQL meta-commands you run from any client:

  • SNAP STATUS — a summary of the mutations you have made (table, operation, count)
  • SNAP DIFF — the full audit log with before/after row data for every change
  • SNAP RESET — reverse all tracked changes, restoring the sandbox to source state
Manual staging Snap
Provisioning time Hours / days Seconds
Storage cost Full copy per environment Only the data you touch
Isolation Shared staging DB Full per-branch isolation
Audit trail None Row-level SNAP DIFF / SNAP RESET
Branching Not possible Unlimited depth
PII masking Hand-rolled scripts Declarative override rules
Agent-safe Manual review required Built for autonomous use

Snap is workspace-scoped like every Destesi product, and is the branching engine other products build on — preview environments fork a branch per pull request, and parallel test runs get a branch each.