---
title: "You already have the automation. You are missing the vault"
description: "Every backup product starts by asking you to adopt its scheduler. That is the wrong first ask, and it is why most teams still have a cron job nobody has looked at since March."
url: "https://saved.sh/blog/you-already-have-the-automation"
date: "2026-08-04"
author: "saved.sh"
tag: "Engineering"
---

Every backup product opens with the same request: install our agent, adopt our
scheduler, let us reach into your network. It is a large ask for something you
have not evaluated yet, and it is almost always the wrong first step.

You already have automation. You have CI, you have a deploy pipeline, you have a
cron entry somewhere that has been quietly running since before the last two
people joined. What you are missing is not a scheduler. It is somewhere safe for
the output to land.

<Aside title="The actual gap">
  A backup has two halves: producing the bytes, and keeping them somewhere the
  thing that produced them cannot reach. Almost every team has solved the first
  half already. Almost none have solved the second.
</Aside>

## The first half is the easy half [#the-first-half-is-the-easy-half]

Here is a complete backup, and it probably looks like something already in your
repository:

```bash
pg_dump "$DATABASE_URL" | gzip > backup.sql.gz
```

That line is fine. It is not the part that fails. What fails is everything after
it: where the file goes, who can delete it, whether anyone notices when it stops
running, and whether the copy is reachable by whatever just compromised the
database.

<Stats>
  <Stat value="1" unit="line" label="to produce a backup" />

  <Stat value="6" unit="problems" label="between that line and a backup you can rely on" />

  <Stat value="0" unit="of them" label="solved by adding a scheduler" />
</Stats>

## The second half is where products should start [#the-second-half-is-where-products-should-start]

So start there instead. Produce the file however you already do, and push it:

```bash
pg_dump "$DATABASE_URL" | sctl backup submit prod-db -
```

No agent. No inbound port. No new scheduler to learn, and nothing to reason about
when it fails, because the thing that runs it is the thing you already trust to
run everything else.

What you get on the other side is the half you were missing. The bytes are
encrypted with your key before they leave the machine, checksummed and recorded,
written under a retention lock, and kept somewhere a compromise of your cloud
account does not reach.

<Figure caption="Terracotta is the reach of one compromised credential. Green is the copy it does not touch. Producing the file was never the hard part.">
  <BlastRadius />
</Figure>

## Adopt the scheduler later, or never [#adopt-the-scheduler-later-or-never]

There is a real argument for handing over the schedule eventually. A durable
engine survives a worker restart and resumes from where it stopped, which a cron
entry cannot do and will not tell you about.

<Figure caption="The same interrupted run, twice. One of these tells you it failed.">
  <DurableRun />
</Figure>

But that is a second decision, and it should be a second decision. Take it when
handing over the schedule buys you something, not as the price of admission.

<Aside title="What we would rather you did" tone="accent">
  Do not migrate anything. Add one line to a pipeline you already run, and see
  whether the copy shows up somewhere you like. If it does, the rest of the product
  is there when you want it. If it does not, you have lost a line of YAML.
</Aside>

## Three levels, and you pick [#three-levels-and-you-pick]

<Figure caption="More handed over as you go down. The right-hand side never changes.">
  <ThreePaths />
</Figure>

Every layer produces the same artifact under the same encryption and the same
retention policy. The only thing that varies is how much of the work you want to
keep doing yourself, and you can change your mind in either direction without
rewriting anything.

Start as a vault. That is the part you are missing.
