Skip to content
Rowsafe

Sleep at night.

Nightly dumps make backups. Rowsafe proves you can restore — to the second.

Continuous WAL archiving, point-in-time recovery, weekly restore drills, monitoring and alerts for the PostgreSQL you already run on your own servers or in Docker. Adopted in place, into your own bucket, without us ever restarting your database.

Free for one server and three databases. PostgreSQL 13+ on Debian, Ubuntu or Docker.

From a read-only plan to a passing restore drill

The CLI's real output. IDs, sizes and times are examples.

  1. $ rowsafe adopt app
    Registered app (db_5k2m9x7q4t1vh). Planning...
    Waiting for the agent to pick up adopt task task_8h3n2c6w1r0zq...
    Running...
    Task task_8h3n2c6w1r0zq: adopt SUCCEEDED
    PostgreSQL 18.0, 12.4 GiB across 2 databases, data directory /var/lib/postgresql/18/main
    Plan (nothing has been changed yet):
    + write pgBackRest config (0600, contains repository credentials) to /etc/rowsafe/pgbackrest/app.conf
    + pgbackrest stanza-create: initialise the repository for this cluster
    ~ archive_mode: off -> on [needs restart]
    ~ archive_command: (disabled) -> /usr/bin/pgbackrest --config=/etc/rowsafe/pgbackrest/app.conf --stanza=app archive-push %p
    ~ archive_timeout: 0 -> 300
    ! PostgreSQL must be restarted for WAL archiving to start. Rowsafe never restarts your database; restart it in a maintenance window, then run `rowsafe db verify`.
    Next: rowsafe apply app

    Plan

    Read-only. With one enrolled host, Rowsafe picks it. The agent inspects PostgreSQL over its Unix socket and lists exactly what it would change.

  2. $ rowsafe apply app
    This changes PostgreSQL settings on db-1 (app) with ALTER SYSTEM and reloads it.
    It never restarts PostgreSQL. Review the plan first with `rowsafe db plan`.
    Apply? [y/N] y
    Waiting for the agent to pick up adopt task task_3v9d0m4k7s2pa...
    Running...
    Task task_3v9d0m4k7s2pa: adopt SUCCEEDED
    PostgreSQL 18.0, 12.4 GiB across 2 databases, data directory /var/lib/postgresql/18/main
    Applied:
    the same five changes and the same restart warning as the plan above
    Next: restart PostgreSQL in a maintenance window (e.g. `sudo systemctl restart postgresql`), then run `rowsafe verify app`.

    Apply

    Writes the pgBackRest config, creates the stanza (the first real test of your bucket and passphrase), then ALTER SYSTEM and a reload. No restart.

  3. $ sudo systemctl restart postgresql@18-main.service

    Restart, on your schedule

    The only downtime, and you run it: usually a few seconds.

  4. $ rowsafe verify app
    Waiting for the agent to pick up check task task_q1w7e5r9t3y0b...
    Running...
    Task task_q1w7e5r9t3y0b: check SUCCEEDED
    app is protected. The first full backup is queued; follow it with `rowsafe tasks app`.

    Verify

    Forces a WAL switch and proves the segment reached your bucket. Schedules start and the first full backup is queued.

  5. $ rowsafe backup list app
    LABEL TYPE FINISHED DURATION DB SIZE STORED
    20260924-140641F full 2026-09-24 14:17 10m52s 12.4 GiB 3.1 GiB

    First backup

    Compressed and encrypted on the host before upload. Your bucket only ever holds ciphertext.

  6. $ rowsafe drill app
    Waiting for the agent to pick up drill task task_m6n2b8v4c0x7d...
    Running...
    Task task_m6n2b8v4c0x7d: drill SUCCEEDED
    Drill PASSED: restored backup 20260924-140641F (12.6 GiB) in 5m41s
    Recovered to the last transaction at Thu, 24 Sep 2026 14:29:51 UTC
    app ok tables 214/214
    postgres ok tables 0/0

    Drill

    Restores the backup plus every archived WAL segment into a socket-only scratch cluster, checks each database, then deletes it.

A nightly dump is a backup nobody has checked.

It captures one moment a day. When the disk fails in the evening, everything since that moment is gone, and nobody knows whether the dump restores.

PostgreSQL hands each WAL segment to Rowsafe as soon as it fills, and at least every 5 minutes on a quiet database (archive_timeout=300).

Nobody has restored it

Unless someone tests it, the first real restore happens during the outage it was meant for. That is when you learn how long it takes, and what is missing.

It isn't the whole cluster

pg_dump copies one database. Roles and other cluster-wide objects need a separate pg_dumpall --globals-only, and are easy to forget.

Success can be silent

A cron job that pipes pg_dump into gzip exits 0 when pg_dump fails, unless the script sets pipefail. The file is there. It just isn't a backup.

Built for the agent era.

Agents now run migrations and destructive SQL, often unattended. When one drops the wrong table, you need to rewind to the second before it, and to know that restore works.

Agent session, Rowsafe MCP tools
you
Drop legacy_orders. orders_v2 replaced it in July.
agent
safety_check {"database": "app"}
PROTECTED: app can be restored to any point from 2026-10-11T01:09:52Z up to about now (WAL last archived 41s ago, last backup 14.0h ago, last drill passed 3d ago).
agent
create_restore_point {"database": "app", "name": "before-drop-legacy-orders"}
Restore point "before-drop-legacy-orders" on app is ARCHIVED (confirmed in the backup repository), LSN 5/2A0001F8.
agent
psql -f migrations/0042_drop_legacy_orders.sql
DROP TABLE
agent
Dropped legacy_orders. Restore point: before-drop-legacy-orders.
you
The invoicing job still reads legacy_orders. It's failing.
agent
Stopping here; I won't try to repair it. You can restore app to before-drop-legacy-orders (restore from backup 20261018-010004F_20261022-010003D).

# on a scratch host: rewind to the name

$ sudo -u postgres pgbackrest --stanza=app --archive-mode=off \
--set=20261018-010004F_20261022-010003D \
--type=name --target=before-drop-legacy-orders --target-action=promote restore
$ sudo systemctl start postgresql@18-main.service
$ pg_dump -h scratch-1 -d app --table=legacy_orders | psql -h db-1 -d app
  • Know before you touch

    safety_check tells the agent whether the database is recoverable right now, and why not if it isn't.

  • A name for the moment before

    create_restore_point returns only once the restore point is stored in your bucket. Then the change runs.

  • Read-only by default

    The MCP server offers read tools until you allow restore points, or writes. No tool runs SQL, restarts PostgreSQL or restores a backup.

Works with Claude Code, Claude Desktop and any MCP client, locally with rowsafe mcp or remotely over HTTPS. The Claude Code plugin's hook creates a restore point before migration commands run, even when the model forgets.

Your server, your bucket. We keep the schedule.

A small agent on the database host runs pgBackRest, the open-source backup tool, and ships everything to storage you own. Rowsafe decides when, keeps the history, and tells you when something is off.

Your server

VPS or bare metal, no inbound ports

PostgreSQL

Your cluster, unchanged except for its archiving settings.

↓ archive_command, every WAL segment

pgBackRest

Compresses and encrypts backups and WAL before upload.

↑ runs backups, checks and drills

rowsafe-agent

Runs as postgres, talks to PostgreSQL over the Unix socket, holds the secrets (0600).

pgBackRest to your bucket: base backups and every WAL segment, AES-256 and zstd.

Your bucket

Cloudflare R2 or any S3-compatible store, on your account. It only ever holds ciphertext.

The agent to Rowsafe: outbound HTTPS only. It asks for work; nothing calls in.

Rowsafe control plane

Schedules, history, dashboard and metrics. Never has your bucket credentials or passphrase.

Agents pull

The agent polls for work over HTTPS and runs only a fixed set of tasks: inspect, adopt, check, backup, drill and restore points.

PostgreSQL archives WAL itself

archive_command calls pgBackRest directly, so point-in-time recovery keeps working even while the agent or Rowsafe is down.

The control plane schedules

By default a full backup on Sundays, a differential the other six nights, and a restore drill every Sunday evening (UTC). Change any of it per database.

Backups, proof, and eyes on the database.

Every plan gets all of it. Plans differ only in how many servers and databases you protect.

  • Continuous WAL archiving

    PostgreSQL hands every WAL segment to pgBackRest through archive_command, so recovery keeps working even while the agent or the control plane is down.

  • Point-in-time recovery

    Restore to any second between the oldest retained full backup and the last archived segment. Two weekly fulls by default: one to two weeks of history.

  • Scheduled full and differential backups

    pgBackRest with zstd, bundling and block incremental. Full on Sunday, differential the other six nights, on cron schedules you can change.

  • Weekly restore drills

    Every Sunday the latest backup and all archived WAL are restored into a scratch cluster, started, and checked database by database.

  • Adopt in place

    No migration and no new server. Rowsafe configures the PostgreSQL you already run, after you read the plan, and never restarts it.

  • Named restore points

    Mark the moment before a risky change. Rowsafe confirms the restore point is in your bucket before the change goes ahead.

  • Built-in monitoring

    Connections, slow queries from pg_stat_statements, long-running and idle transactions, locks, disk, WAL rate, transaction ID wraparound headroom, and host CPU and memory.

  • Alerts where you work

    Missed backups, failing WAL archiving, failed drills and monitoring problems, sent by email or to Slack, Discord or any webhook.

  • Host or Docker

    Install the agent on Debian or Ubuntu with one command, or run it as a sidecar next to the official postgres image.

  • Agent-ready

    An MCP server lets coding agents check protection and create restore points. Read-only unless you allow more.

  • Self-updating agent

    Signed releases, a self-test before every switch, probation, and automatic rollback if a new version misbehaves.

  • Your bucket, your keys

    Backups go to your own S3-compatible bucket, encrypted on the host. Bucket credentials and the passphrase never leave the server.

A backup you haven't restored is a guess.

Every Sunday, Rowsafe restores each database next to production and checks it. You find out a restore fails on a quiet evening, not in the middle of an outage.

  1. Checks free disk first: at least 1.3 × the cluster size + 1 GiB, or the drill refuses to start.

  2. Restores the latest backup plus every archived WAL segment with pgbackrest restore, at low CPU and IO priority, with archiving off.

  3. Starts the copy on a private Unix socket with no TCP listener, and waits for recovery to finish.

  4. Compares every database with production. A missing database, or one restored empty, fails the drill.

  5. Stops the scratch cluster and deletes its directory, whatever the outcome.

$ rowsafe drill list app
WHEN RESULT BACKUP RECOVERED TO DURATION DATABASES
2026-10-18 21:15 PASSED 20261018-010004F 2026-10-18 21:14:37 6m3s 2
2026-10-11 21:15 PASSED 20261011-010002F 2026-10-11 21:14:52 5m58s 2
2026-10-04 21:15 PASSED 20261004-010003F 2026-10-04 21:14:41 5m52s 2
2026-09-27 21:15 PASSED 20260927-010005F 2026-09-27 21:14:49 5m47s 2
2026-09-24 14:30 PASSED 20260924-140641F 2026-09-24 14:29:51 5m41s 2

Four scheduled drills after the first one. Each row says which backup was restored, the last transaction it recovered, and how long it took: your real restore time, measured weekly.

See trouble coming. Hear about it where you work.

The same agent watches the database while it guards the backups. The dashboard shows what PostgreSQL is doing, and alerts reach you before a full disk or a stuck transaction becomes an outage.

Built-in monitoring

Connections
By state and database, against max_connections.
Query performance
The slowest and most frequent statements from pg_stat_statements.
Long and idle transactions
Sessions stuck in a transaction or idle in transaction.
Locks
Who is waiting on whom.
Disk
Data directory and pg_wal growth, and free space.
WAL rate
How fast WAL is written, and how far archiving lags.
Wraparound headroom
Transaction IDs left before PostgreSQL must freeze.
Host
CPU, memory and load of the database server.

Built-in alerts

  • Email
  • Slack
  • Discord
  • Webhook

You hear about:

  • Backups missing or failing, and no recent full backup
  • WAL archiving failing or falling behind
  • Restore drills failing or overdue
  • PostgreSQL unreachable, or the agent offline
  • Monitoring problems such as disk filling up, blocked locks or shrinking wraparound headroom

Runs where your PostgreSQL runs.

On a Debian or Ubuntu server, or in Docker next to the official image. The dashboard prints the exact command with a one-time enrollment token.

On the host

Debian 12/13 or Ubuntu 22.04/24.04, amd64 or arm64. The installer checks the release signature before it touches anything, installs pgBackRest if it is missing, and runs the agent under systemd as postgres.

Install the agent
$ curl -fsSL https://rowsafe.sh | sudo sh -s rse_...

https://rowsafe.sh/install serves the same script. Then, from your machine: rowsafe login and rowsafe adopt app.

In Docker

Add a sidecar to your existing compose file. Your postgres service keeps its stock image.

compose.yml: lines to add (+)
 services:
   postgres:
     image: postgres:17
     volumes:
       - pgdata:/var/lib/postgresql/data
+      - pgsocket:/var/run/postgresql
+      - rowsafe-spool:/rowsafe-spool
+
+  rowsafe-agent:
+    image: ghcr.io/rowsafe/agent:<version>-pg17
+    hostname: db-1
+    user: "999:999"
+    restart: unless-stopped
+    depends_on: [postgres]
+    env_file: rowsafe-agent.env
+    shm_size: 256m
+    volumes:
+      - pgdata:/var/lib/postgresql/data:ro
+      - pgsocket:/var/run/postgresql
+      - rowsafe-spool:/rowsafe-spool
+      - rowsafe-state:/var/lib/rowsafe

 volumes:
   pgdata:
+  pgsocket:
+  rowsafe-spool:
+  rowsafe-state:
  • PostgreSQL stays on the stock postgres image. The agent is a sidecar that mounts the data volume read-only, the socket volume, and a spool volume.
  • archive_command copies each WAL file into the spool and fsyncs it; the agent pushes it to your bucket with pgBackRest, in order, and deletes it only once it is stored.
  • Restore points and rowsafe verify count only once the WAL is in the bucket: the agent fetches the segment back from the bucket before it reports a restore point as archived.
  • PostgreSQL 18's new data layout is handled: mount the volume at /var/lib/postgresql in both services and use the -pg18 tag.
  • Agent images are Debian-based, about 370 MB, tagged <version>-pg14 to -pg18, with -alpine variants for the Alpine postgres images. Update by changing the tag; the agent doesn't update itself in Docker.
  • Linux hosts only for production. Adding the mounts recreates the postgres container: a few seconds of downtime.

Built to be trusted with production.

Rowsafe touches the most important process on your server. So it asks first, changes as little as possible, and can't reach your data.

Plan before apply
Adopting a database prints a read-only plan. Nothing changes until you run rowsafe apply, and an existing archive_command is never replaced without --force.
Never restarts PostgreSQL
Settings that need a restart are written with ALTER SYSTEM. You restart in your own maintenance window, then verify.
Isolated drills
Drill clusters listen on a private Unix socket only, run with archiving off at low CPU and IO priority, and are deleted afterwards.
Signed updates, probation, rollback
The agent runs only releases signed with an Ed25519 key compiled into it. It refuses downgrades, self-tests a new version, and rolls back one that fails.
Secrets stay on your host
Bucket credentials and the encryption passphrase live in /etc/rowsafe on the database host (mode 0600). The control plane never receives them.
Client-side encryption
Backups and WAL are encrypted with aes-256-cbc before they leave the host. Your bucket holds only ciphertext.
Outbound only
The agent makes outbound HTTPS requests and listens on nothing. It runs one of a fixed set of tasks and never executes commands sent to it.
Open-source agent
Everything that runs on your servers (agent, CLI, installer) is open source under Apache-2.0, so you can audit every line that touches your database.

Keep your server. Get the recovery of a managed database.

How Rowsafe compares with the two usual answers. These are categories, not vendors: details vary by provider, so check yours.

Rowsafe compared with nightly pg_dump or scheduled dump services, and with fully managed PostgreSQL
QuestionNightly pg_dump or a scheduled dump serviceFully managed PostgreSQLRowsafe
Where PostgreSQL runsYour serverThe provider's infrastructureYour server, unchanged
Data you can loseEverything since the last dump: up to 24 hours with a nightly jobDepends on the provider; point-in-time recovery is commonAbout 5 minutes at most on a quiet database, less on a busy one
Restore to a moment in timeNo, only to when a dump ranUsually, within the provider's retention windowYes, to the second, or to a named restore point
Restores testedOnly if you build and run the test yourselfThe provider's responsibilityEvery week, every database, with a report you can read
Where backups liveWherever you copy themThe provider's storageYour own bucket, encrypted before upload
Who can decrypt themWhoever you give the files or key toThe provider, or a key you manage in their KMSOnly holders of your passphrase
Migration neededNoneYes, your data moves to the providerNone; one restart in your own window
Control over version, extensions and tuningFullWhatever the provider supportsFull
Monitoring and alertsBuild it yourselfUsually includedBuilt in: queries, locks, disk, WAL, wraparound, host; email, Slack, Discord, webhook
Replicas and automatic failoverNoUsually availableNot yet (on the roadmap)

Priced by servers, not by gigabytes.

Every plan gets every feature. You choose how many servers and databases to protect, and your bucket stores the backups, so the price never grows with your data.

  • Free

    One server, fully protected.

    $0forever

    Servers
    1
    Databases
    3
    • Continuous WAL archiving and point-in-time recovery
    • Weekly full and daily differential backups
    • Weekly automated restore drills
    • Named restore points
    • Monitoring and alerts
    • MCP server for AI agents
    • Retention and schedules you set per database
    • Dashboard, CLI and API keys
    • Health issues for missed backups, WAL archiving and drills
    • Signed agent auto-updates with rollback
    • Audit log
  • Pro

    For teams running a handful of Postgres servers.

    $39per month

    Servers
    5
    Databases
    25
    • Continuous WAL archiving and point-in-time recovery
    • Weekly full and daily differential backups
    • Weekly automated restore drills
    • Named restore points
    • Monitoring and alerts
    • MCP server for AI agents
    • Retention and schedules you set per database
    • Dashboard, CLI and API keys
    • Health issues for missed backups, WAL archiving and drills
    • Signed agent auto-updates with rollback
    • Audit log
  • Business

    For fleets that can't afford to lose a row.

    $149per month

    Servers
    25
    Databases
    200
    • Continuous WAL archiving and point-in-time recovery
    • Weekly full and daily differential backups
    • Weekly automated restore drills
    • Named restore points
    • Monitoring and alerts
    • MCP server for AI agents
    • Retention and schedules you set per database
    • Dashboard, CLI and API keys
    • Health issues for missed backups, WAL archiving and drills
    • Signed agent auto-updates with rollback
    • Audit log

Prices in USD per organization, billed monthly; cancel anytime. Payments are processed by Polar, our merchant of record, which handles sales tax and VAT. Storage is billed by your bucket provider, not by us.

Compare plans

Features and limits by plan
FeatureFree$0Pro$39 per monthBusiness$149 per month
Servers1525
Databases325200
Backups and recovery
Continuous WAL archivingIncludedIncludedIncluded
Point-in-time recoveryIncludedIncludedIncluded
Weekly full and daily differential backupsIncludedIncludedIncluded
Retention and schedules per databaseIncludedIncludedIncluded
Client-side encryption to your own bucketIncludedIncludedIncluded
Proof
Weekly automated restore drillsIncludedIncludedIncluded
Named restore pointsIncludedIncludedIncluded
Monitoring and alerts
Monitoring dashboardIncludedIncludedIncluded
Alerts on backups, WAL archiving and drillsIncludedIncludedIncluded
Email, Slack, Discord and webhook notificationsIncludedIncludedIncluded
Tools
Dashboard, CLI and API keysIncludedIncludedIncluded
MCP server for AI agentsIncludedIncludedIncluded
Audit logIncludedIncludedIncluded
Host installer or Docker sidecarIncludedIncludedIncluded
Signed agent auto-updates with rollbackIncludedIncludedIncluded
Start free (Free plan)Start with Pro (Pro plan)Start with Business (Business plan)

Billing

What counts as a server and a database?

A server is a host with the Rowsafe agent enrolled. A database is one PostgreSQL cluster you adopt on that host (one host and port); every database inside that cluster is backed up and checked together.

How does billing work?

Paid plans are billed monthly, in USD. Payments are processed by Polar, our merchant of record, so Polar calculates and collects sales tax or VAT where it applies and issues the invoices. Upgrades take effect as soon as Polar confirms the payment, and plan changes are prorated.

Can I cancel anytime?

Yes, from the billing page in the dashboard. Your plan stays active until the end of the paid month, then the organization moves to Free. Nothing is deleted: backups, schedules and drills keep running; you just can't add servers or databases beyond the Free limits.

Questions, answered plainly.

Does Rowsafe ever restart my database?

No. Settings that need a restart (archive_mode, and wal_level if it is minimal) are written with ALTER SYSTEM. You restart PostgreSQL in your own maintenance window, usually a few seconds of refused connections, then run rowsafe verify.

What does the database host need?

PostgreSQL 13 or newer on Debian 12/13 or Ubuntu 22.04/24.04 (amd64 or arm64), a postgres user, and outbound HTTPS. The installer verifies a signed release and installs pgBackRest if it is missing. Nothing needs to listen for inbound connections.

Does it work with PostgreSQL in Docker?

Yes, on Linux hosts. PostgreSQL stays on the stock postgres image (14 to 18, Debian or Alpine). The agent runs as a sidecar, ghcr.io/rowsafe/agent:<version>-pg<major>, that mounts the data volume read-only, the socket volume and a spool volume: PostgreSQL copies each WAL file into the spool and the agent pushes it to your bucket. Backups, drills, restore points, monitoring and alerts work as on a host. You update the agent by changing its image tag.

What does the monitoring collect?

Connections, query statistics from pg_stat_statements (when the extension is enabled), long-running and idle-in-transaction sessions, locks, disk usage, WAL rate, transaction ID wraparound headroom, and host CPU and memory. Query statistics are normalized: literal values are replaced by placeholders. Row data never leaves your server.

Where do alerts go?

Email, Slack, Discord, or any webhook, on every plan. You get alerts for missed or failed backups, failing WAL archiving, failed or overdue drills, an unreachable database or offline agent, and monitoring problems such as a filling disk.

Which storage can I use?

Any S3-compatible bucket you own. The docs use Cloudflare R2; MinIO and other S3-compatible stores work through the same settings. Give Rowsafe a private bucket and a token scoped to it, and don't add a lifecycle rule that deletes objects: pgBackRest expires old backups and WAL itself.

How much data can I lose?

PostgreSQL archives each WAL segment as it fills, and Rowsafe sets archive_timeout=300, so on a quiet database at most about 5 minutes of writes are not yet in the bucket. A nightly pg_dump can lose up to 24 hours.

How far back can I restore?

From the end of the oldest retained full backup to the last archived WAL segment. Rowsafe keeps 2 full backups by default, with a full backup every Sunday: about one to two weeks. Set retention and schedules per database with rowsafe db set.

Can Rowsafe read my data?

No. Backups are encrypted on your host before upload, and the bucket credentials and passphrase stay on the host. The control plane stores metadata only: hostnames, database names and sizes, table counts, PostgreSQL settings, task logs and monitoring metrics.

What happens if Rowsafe is down?

PostgreSQL keeps archiving WAL through archive_command, which needs only pgBackRest on your host, so point-in-time recovery keeps working. Scheduled backups and drills resume when the control plane is back.

How do I restore?

Today, with pgBackRest, following the restore runbook: to the latest point, a moment in time, or a named restore point, onto a new host or a scratch cluster. The weekly drill runs the same restore, so you know it works and how long it takes.

What if I lose the encryption passphrase?

Then nobody can restore those backups, Rowsafe included. Store the passphrase in your secret manager, and a second place, before the first backup exists.

Does it do replicas and failover?

Not yet. Rowsafe protects and proves your backups today. Standby replicas with automatic failover are on the roadmap.

Is it open source?

Everything that runs on your servers is: the agent, the CLI (including rowsafe mcp and the Claude Code plugin) and the installer are Apache-2.0, on GitHub. The control plane and dashboard that Rowsafe runs for you are proprietary.

Should I keep my existing backups?

Yes, for a while. The adoption runbook suggests running your old job in parallel for 30 days: four passing drills and one manual restore, then retire it.

Not built yet

Rowsafe protects and proves the PostgreSQL you run today. Restoring production is a documented pgBackRest procedure. These come later, and we'll say so here when they ship.

  • Coming

    Standby replicas and automatic failover

    A streaming replica on a second server, promoted automatically when the primary is lost.

  • Coming

    Managed hosting

    Rowsafe runs the PostgreSQL server too, with the same backups and drills.

  • Coming

    More engines

    PostgreSQL first. Other databases after that.

Sleep at night.

Adopting a production database takes about an hour of work and one short restart in your window. The first drill tells you it worked.