---
title: "Sources"
description: "What a backup can take, and where each type is allowed to run."
url: "https://saved.sh/docs/backups/sources"
---

A source type decides what a run produces and which kinds of backup may use it. It is set
when you configure the backup and can be changed later, unlike `kind`.

## The table [#the-table]

| Type                                         | `local` | `cloud`   | Produces                      | Needs       |
| -------------------------------------------- | ------- | --------- | ----------------------------- | ----------- |
| [`postgres`](/docs/backups/sources/postgres) | Yes     | Yes       | Custom-format dump            | `pg_dump`   |
| [`mysql`](/docs/backups/sources/mysql)       | Yes     | Yes       | SQL dump                      | `mysqldump` |
| [`redis`](/docs/backups/sources/redis)       | Yes     | Yes       | JSON Lines of `DUMP` payloads | none        |
| [`s3`](/docs/backups/sources/s3)             | Yes     | Yes       | One tar                       | Nothing     |
| [`web`](/docs/backups/sources/web)           | Yes     | Yes       | The response body             | `curl`      |
| [`script`](/docs/backups/sources/script)     | Yes     | **Never** | Whatever you write            | Nothing     |
| [`file`](/docs/backups/sources/files)        | Yes     | **Never** | The file                      | Nothing     |
| [`folder`](/docs/backups/sources/files)      | Yes     | **Never** | One zip                       | Nothing     |

The **Needs** column applies to local backups only: those are tools that must exist on your
worker's host. For cloud backups we provide them.

Submitting a type that is illegal for the kind is refused when you save the definition,
naming the type you sent.

## A run produces exactly one artifact [#a-run-produces-exactly-one-artifact]

Sources that are naturally many files, `s3` and `folder`, are streamed
into a **single archive**. That keeps `keep_last` counting runs rather than files, and keeps
one restore one operation.

Streamed, not staged: the archive is written as objects are read, so backing up a 400 GB
bucket does not need 400 GB of scratch space for the listing pass.

## Local-only, permanently [#local-only-permanently]

`script`, `file` and `folder` will never be available as cloud backups.

* **`script`** runs a command you wrote. Executing customer commands in our cloud is a
  sandboxing and abuse problem we are not taking on.
* **`file` and `folder`** read your filesystem. There is nothing for our cloud to connect to,
  and a remote copy of your disk would be a different product with a different trust story.

This is a guarantee rather than a roadmap gap: the workflows for these three are not
registered on our side at all, so there is no configuration that could route one there.

`script` is also the most useful type in the list, precisely because of the constraint. It
lets you back up anything we have no connector for, on your own hardware, with no work from
us.

## Where the credential lives [#where-the-credential-lives]

| Kind     | Source configuration                                  | Secrets                                   |
| -------- | ----------------------------------------------------- | ----------------------------------------- |
| `local`  | Your worker's `config.yaml`                           | Never leave your machine                  |
| `cloud`  | Public half in our database, secret half in our vault | Written by the API, never read back by it |
| `manual` | There is none                                         | There is none                             |

For a cloud backup, every source type declares which of its fields are public and which are
secret. The API returns the public half only. See
[the public/secret split](/docs/backups/cloud#where-the-credential-lives).

## Changing source type [#changing-source-type]

Allowed, and it applies to future runs. Existing artifacts are untouched and still restore as
whatever they were.

Two things happen automatically:

* A source payload whose fields do not match the new type is refused, so a form that changed
  the type and kept stale fields cannot store a mismatch.
* A `local` backup's worker keeps the old type in its own `config.yaml` until you edit it
  there too, and the next run fails with `SourceTypeMismatch` rather than dumping the wrong
  thing. Change both sides.

If the new source is really a different thing being backed up, prefer a new backup. Retention
is per backup, and mixing two sources under one policy makes the artifact list harder to
reason about than it needs to be.
