TILLARK · TILLDEV

Prove your last N restores
all passed.

Cross-vendor backup and disaster recovery, with restore-verification you can actually prove. On a schedule, TillArk restores your backups into throwaway sandboxes, checks they’re intact, and shows pass or fail with the real RPO and RTO. Backup is a trust category; we earn it by verifying, not by hoping.

PROVING · restore-verification
3-2-1 · cross-vendor · object lock · encrypted in the agent · hybrid-pqc · verified
WHAT’S INSIDE

A control plane for recovery.

Restore-verificationGA

On a schedule, the agent restores a backup into a throwaway sandbox, runs the checks for its type, and tears it down. Pass or fail, with the observed RTO, lands on your board and in your notifications. Older backups are proven in turn, and a restic repository is read in parts until every stored byte is checked. A run’s stores verify and restore together as of one moment where each store’s backup allows it, versioned buckets included; the run says plainly when a store can’t, and every row that names a missing object is reported.

› Read the docs
Point-in-time recoveryGA

WAL-G or pgBackRest archives PostgreSQL’s write-ahead log to your targets as it is written, so a restore can land on any moment in the window, not only on a backup. Anti-affinity keeps every copy on another vendor and region.

› Read the docs
FailoverPREVIEW

Move a PostgreSQL primary to a replica on request, or automatically when observers agree it is down, even while TillArk itself is unreachable: the old primary is fenced first, and a replica is promoted only when its measured lag is in bounds. Your Cloudflare DNS records, or your webhook, move clients to it before it takes writes. Runs on Neon and on PostgreSQL you run, with logical replication or streaming replication across up to nine servers.

› Read the docs
Encrypted before uploadGA

The agent encrypts every backup before it leaves your environment, so the storage vendor only sees ciphertext. Credentials reach the agent sealed with hybrid post-quantum key exchange.

› Read the docs
Object-locked targetsGA

With object lock, a backup can’t be deleted or overwritten inside its retention window, and the agent confirms the lock before every write. A policy can require copies under separate credentials.

› Read the docs
Engines wrapped, not rebuiltGA

restic, WAL-G, pgBackRest and clickhouse-backup, plus each datastore’s own dump tools, driven by a Go agent you run, across S3, R2, B2, Wasabi, GCS, Azure, MinIO and SFTP. We own the manifest, not a backup engine.

› Read the docs
THE WEDGE

Anyone can take a backup. The question is
whether it restores.

On a cadence, TillArk restores a real backup into an ephemeral, network-isolated, per-tenant sandbox, asserts its integrity — signature, schema hash, row counts, checksums — tears it down, and emits the result. Every bar below is one real restore that actually happened, with the RPO and RTO it measured.

RTO SLO · 60s← 30 DAYS · ONE PROVING-RESTORE PER DAYLATESTRTO 47sRPO 1m30 / 30 PASSED→ Recovery Board

This turns “we take backups” into “we’ve proven the last N restores worked.” A silent failure — expired credentials, a changed bucket policy, quiet corruption — surfaces as a red restore on a board, not as a discovery at 3 a.m. during the outage you were saving for.

It is the honest, monitored SLA the incumbents don’t offer — and each policy sets its own verification schedule, so you choose how often proof runs.

Proof covers what you keep, not just the newest copy. Verifications on one schedule start staggered, older backups are proven in turn, and on restic each verification reads one more part of the stored data against its hashes, so over thirty runs every stored byte has been read.

Restore-verification guide →
bash · verify
$ tilldev ark restores

WHEN    KIND    STATUS  TO          PROVED                   APPROVED BY  BACKUP        ID
4h ago  verify  passed  backup end  newest, part 12/30 read  -            7f3a9c21-4e…  19c0e2b4-…
1d ago  verify  passed  backup end  older, part 11/30 read   -            52e0b1f4-9a…  18f2a7c1-…
2d ago  verify  passed  backup end  newest, part 10/30 read  -            0c9d77aa-31…  18a1d05e-…
3d ago  real    passed  backup end  -                        4b1e90d2-…   0c9d77aa-31…  1873bb6f-…
3-2-1, AUTOMATED

Backups land on a different failure domain.

Scheduled backups and a continuous WAL archive go to the targets you choose, and residency-aware anti-affinity makes sure each copy lands on a different vendor and region than the source — but never outside the residency zone it’s allowed in. A copy in the same blast radius isn’t a backup.

RESTIC · HOURLYWAL-G OR PGBACKREST · CONTINUOUSRESTIC · HOURLYSOURCEpostgres · aws · eu-westCOPY 1 · OTHER VENDORb2 · eu-central · object lockVERIFIEDWAL ARCHIVE · PITRinto both copies · any momentRPO ~minCOPY 2 · OTHER REGIONgcs · eu-north · separate keysVERIFIEDANTI-AFFINITY · DIFFERENT VENDOR + DIFFERENT REGION · SAME RESIDENCY ZONE (eu)
yaml · policies.yaml
# The policy is the contract. Review it like code.
version: 1
policies:
  - source: orders-db
    schedule: "0 * * * *"
    rpo: 1h15m
    rto: 15m
    retention:
      hourly: 24
      daily: 30
      monthly: 12
    placement:
      residency: eu
      copies: 2
      separate_credentials: true
    verify:
      cadence: "0 4 * * *"
bash · plan
$ tilldev ark plan policies.yaml
Plan: 1 to change.
  ~ orders-db / default
      retention.daily                 7 → 30
      placement.residency             global → eu
      placement.copies                1 → 2
      placement.separate_credentials  false → true
      rto                             1h → 15m
      verify.cadence                  0 6 * * * → 0 4 * * *

$ tilldev ark apply policies.yaml

Keep every policy in one file next to your code. A plan shows exactly what a change does and flags one that keeps fewer backups or loosens where copies may land; apply makes every change or none, each in the audit log. Hourly backups, two copies on other vendors and regions inside the EU under separate keys, and a real restore proven every day at 04:00 UTC.

ROLES, NOT MACHINES · PREVIEW

Failover you can actually trust.

There is a primary role and a replica role, and roles move between nodes — which dissolves the “original vs backup” confusion at the heart of a botched failback. A failover fences the old primary first, then promotes a replica whose lag is measured and in bounds. Before it takes writes, the agent points your DNS records at it or tells your webhook; without either, you repoint your app. To come home, reseed the old primary from the new one and fail back: the agent proves it holds every committed write before it switches. Or finish the failover and keep the new primary.

Automatic failover is opt-in. By default a failover waits for an admin and a second approver, because the fast wrong answer during an incident is worse than the careful right one. Arm it per source once observers watch the primary from where your application runs, and turn on autonomy so an outage that also cuts you off from TillArk still fails over. Failover is in preview, on Neon and on PostgreSQL you run.

Failover reference →
bash · failover
# Where does the source stand right now?
tilldev ark failover status --source <source-id>

# Promote a replica: fences the old primary first, refuses a stale one.
# Needs a second, distinct approver (four-eyes).
tilldev ark failover promote --source <source-id> \
  --approved-by <user-id> --approval-ref INC-4821

# Rebuild the old primary as a replica of the new one (four-eyes too).
tilldev ark failover reseed --source <source-id> --node <provider:region> \
  --approved-by <user-id> --approval-ref INC-4821

# Come home deliberately: the agent proves the old primary caught up, then switches.
# Never automatic.
tilldev ark failover failback --source <source-id> \
  --approved-by <user-id> --approval-ref INC-4821
4-EYES REQUESTFENCE FIRSTLAG ≤ 30 s · RE-MEASUREDRESEED OLD PRIMARY4-EYES FAILBACKFENCE · DRAIN · FLIPHEALTHYprimary servingSUSPECTapproved requestFENCINGno more writesPROMOTEDreplica → primaryREVERSE-SYNCreplicates backFAILBACKproven caught up⚠ NEVER RESUME THE OLD WRITE DIRECTIONSECOND APPROVER · ONE FAILOVER AT A TIME · PREVIEW
GUARDRAILS, BY DEFAULT
four-eyes

An owner or admin requests the failover, or arms automatic failover, and a different one approves it. One person, or one leaked token, can’t move your primary.

confirm

Automatic failover waits until a quorum of observers, one of them where your application runs, has not reached the primary for the whole confirm window. A partition or a blip is not an outage.

fence

The old primary is fenced before promotion — on Neon its compute is suspended and its role password reset; on PostgreSQL you run, your application’s roles are locked out and it turns read-only — so your application can’t write to it even if it is still alive. Nothing is fenced unless a replica could be promoted, and if fencing fails, nothing is promoted.

lag bound

A replica is promoted only with a lag measured in the last 5 minutes and at most 30 seconds, measured again just before promoting; in an outage, as it stood when the primary went down. Unknown lag is never treated as zero.

autonomy

Opt in, with a second approver, and the replica’s agent can fail over on its own when TillArk itself is unreachable: on the same rules, under a grant TillArk signs with Ed25519 and ML-DSA-65, and rechecked from the observers’ signed reports once it reports back.

anti-flap

A cap per window and a cooldown after any failover stop ping-pong, and a failed failover stops automatic failover until someone re-arms it.

catch up first

One failover at a time per source. Failback is a deliberate switchover once the old primary has caught up — never an automatic flip.

clients follow

After fencing and before the promoted node takes writes, the agent points your Cloudflare DNS records at it and reads them back, or calls your signed webhook, which can refuse. If the promotion fails, clients are pointed back. Records that drift from the primary are flagged.

synchronous

On PostgreSQL you run, see whether each replica holds every commit the primary acknowledged, and why not; let the agent keep synchronous replication set, on one standby or a quorum of several. When one of up to nine servers is promoted, the other standbys follow it, and it never inherits a wait for a standby that isn’t there.

three tiers

Each source shows three durability tiers side by side: a synchronous replica, a replica on another provider that could take over, and a continuous WAL archive. When one lapses, an alarm opens; when it holds again, it closes.

SECURITY IS THE SPINE

The vendor holds bytes it
can’t read — and can’t delete.

Backups are the single highest-value target an attacker can steal once and hold forever, so TillArk is designed as if the ciphertext is already stolen. Data is encrypted inside the agent, before it leaves your environment, and written to object-locked storage with credentials sealed to one approved agent.

Whole classes of bug are made structurally absent, not merely filtered: command injection (CWE-78) can’t occur because the agent only ever builds argv arrays, and SSRF (CWE-918) can’t reach your metadata endpoint because every storage host is re-resolved and IP-pinned, and link-local and metadata addresses never pass.

THE SECURITY MODEL
Encrypted in the agent

restic, WAL-G and pgBackRest encrypt every backup, clickhouse-backup’s included, before upload — the storage vendor only ever sees ciphertext.

Verify before restore

Hybrid-signed manifests (Ed25519 + ML-DSA-65) are checked before a single byte is trusted.

Object lock

The agent confirms a target’s lock before every write; a locked backup can’t be deleted or overwritten inside its retention window.

Separate credential domains

A policy can keep its copies under different keys, so one leaked key can’t reach them all; under compliance-mode lock, no key can erase a backup early.

Crypto-agility + PQC

Every envelope names its suite, so primitives rotate without breaking old backups. Hybrid post-quantum ready.

Four-eyes on danger

Real restores, failover and unmasked clones need a second, distinct owner or admin to approve.

OWN THE CONTROL PLANE, NOT THE BYTES

Engines wrapped, not rebuilt.

A homegrown backup engine’s failure mode is silent data loss you discover at restore time. TillArk doesn’t build one — it drives proven engines with a self-hostable Go agent (a single static binary that runs in your environment, so data and credentials stay on your side). Our originality goes into the manifest, the verification, and the orchestration.

CONTENT-ADDRESSED · INCREMENTAL-FOREVER
restic

Dedup, compression, and encrypt-then-upload straight to object storage. The workhorse for files, buckets, and most datastores.

POSTGRES · PHYSICAL + PITR
WAL-G

Parallel physical backups and continuous WAL archive for Postgres — the foundation under point-in-time recovery. Delta backups store only the pages that changed, and every backup a chain holds is checked against its signed manifest.

POSTGRES · PHYSICAL + PITR · SFTP TOO
pgBackRest

The same continuous WAL archive, on object storage or an SFTP server, with differential and incremental backups between fulls. Every file is checked against its checksum on restore, and every WAL segment before recovery replays it.

CLICKHOUSE · TABLE PARTS
clickhouse-backup

Copies MergeTree tables’ data parts from a snapshot instead of reading every row, so large ClickHouse servers back up without a full export. Proven by restoring the parts and running CHECK TABLE on every table.

EACH DATASTORE · ITS OWN FORMAT
native dump tools

pg_dump, mysqldump or mariadb-dump, mongodump, the Redis protocol, Meilisearch’s API, ClickHouse’s native format and a TillForge git server’s own sealed backup, streamed straight into restic.

STORE IT ANYWHERE — CROSS-VENDOR BY DESIGN
S3R2B2WasabiGCSAzureMinIOSFTP
WHAT BEING THE BACKUP UNLOCKS

Two things only the backup can do.

OBSERVABILITY-NATIVE
GA

Ransomware canary

A backup system sees every byte’s compressibility. When a datastore’s backups turn high-entropy and stop deduplicating, something is encrypting your data. TillArk raises the alarm on the first backup that shows it, quarantines that backup so no one restores it, and can pause the source.

HOW IT WORKS · Every backup’s entropy and dedup ratio are signed into its manifest and charted on your Recovery Board. When entropy jumps and dedup collapses together, judged against that source’s own history, the canary fires.

DEV VALUE
GA

Masked clones

A PostgreSQL clone of last night’s backup with personal data masked column by column, using the same rules as the SDK’s on-device scrub (M-Pesa, national ID, phone, email). Realistic data to build and test against, without real customer data on a dev box.

HOW IT WORKS · An agent on your own host masks rows as it copies them, so unmasked rows never reach the clone, then serves it over verified TLS with a list of every masked column. It expires on a timer; an unmasked clone needs four-eyes approval.

NOT A SILO

Same workspace. Same login.

TillArk isn’t a separate DR appliance to run — it’s the recovery layer of the TillDev workspace you already have. It reuses TillSecrets for keys, TillAuth for approvals, and reports every number to TillPulse.

01 · REPORTS TO

TillPulse

Live RPO/RTO, replication lag with SLO alarms, restore-verification green/red history, and failover transitions land in the same observability surface as the app they protect.

02 · BUILT ON

The suite

Keys come from TillSecrets, RBAC and four-eyes approvals from TillAuth, and outbound safety from the shared SSRF guard. TillArk is enterprise-grade because the suite already is.

03 · RECORDS

One audit log

Every backup, restore, promotion, fence and key rotation lands in an audit log where each entry is chained to the one before by hash and TillArk signs checkpoints over the chain. Check it on your own machine with tilldev ark audit verify. It sits in your workspace audit log next to your Pulse, Auth and Shield events.

FAILOVER IN PREVIEW

Backups, restores, verification, the canary and masked clones are ready. Failover is in preview and runs on Neon. Whatever TillArk runs, it never reports a backup or a restore that didn’t happen.

TURN IT ON

Stop hoping your backups restore. Prove it — cross-vendor, encrypted before it leaves your box, immutable at rest, and verified on a schedule you can watch.

PART OF TILLDEV

It closes the loop.

TillArk protects the rest of the suite — same workspace, same audit log, same login. Add what you need when you need it.