> For the complete documentation index, see [llms.txt](https://docs.emseapea.ai/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.emseapea.ai/setting-up-your-accounts/somewhere-to-keep-files-and-data.md).

# Somewhere to keep files and data

Your apps will create files and records of their own — uploaded receipts, a generated PDF, a rota. **Settings → Storage** is where you decide, once, which places are on offer for that; [Somewhere for apps to keep things](/admin-guide/storage.md) explains the screen in full. This page is only about **the accounts you have to go and create first**, and which of them Emseapea can actually do anything with.

Start from the sentence the product itself refuses to paraphrase anywhere:

> A storage class decides where an app keeps its data. It never decides what the app puts there.

And from the one that tells you what defining a class does and does not create:

> Defining a class creates nothing on its own. This is the list of places you have agreed apps may use. A Cloudflare R2 file store is set up for real the next time you deploy your gateway; everything else on this list is a place you already have.

That second quote is the whole of this page in miniature. **Emseapea provisions exactly one thing on the list.** Everything else is somewhere you set up yourself, in your own account, with your own credentials — and for most of the list there is nowhere in Emseapea to put those credentials, because nothing would read them.

## The list, and what each one asks of you

| Provider                          | Keeps    | What you create                            | Status                                                           |
| --------------------------------- | -------- | ------------------------------------------ | ---------------------------------------------------------------- |
| **Cloudflare R2**                 | Files    | Nothing — Emseapea creates the store       | **Built, but never used against a real account**                 |
| **Amazon S3**                     | Files    | The bucket, in your own AWS account        | **Not built yet** — a name on a list                             |
| **Azure Blob Storage**            | Files    | The container, in your own storage account | **Not built yet** — a name on a list                             |
| **Cloudflare D1**                 | Database | The database, and a credential for it      | **Not built yet** for the gateway route; direct connections work |
| **Neon Postgres**                 | Database | The database, and a role for the app       | Same                                                             |
| **Amazon RDS for PostgreSQL**     | Database | The database, and a role for the app       | Same — direct connection only                                    |
| **Azure Database for PostgreSQL** | Database | The database, and a role for the app       | Same — direct connection only                                    |

## Cloudflare R2 — the only one Emseapea creates

You create nothing. When your organization's gateway is deployed, Emseapea creates the bucket and mints a key that reaches that bucket and nothing else, and puts that key on the gateway as a secret — it is never written into Emseapea's database.

Four things to know before you rely on it.

**It is created in Emseapea's Cloudflare account, not yours** — the same account the gateway itself runs in today. See [Cloudflare, for the gateway we include](/setting-up-your-accounts/cloudflare-for-the-gateway.md).

**Nobody has done this for real yet.** Buckets have been created, written to and deleted against a live Cloudflare account by hand, so the mechanism is known to work. But the bucket-scoped key has never been minted through the product, and **no governed app has ever written a real file through a real gateway.** Whether the Cloudflare token in use even carries the two permissions this needs has never been checked. If it does not, the gateway deploy reports the file store as not set up — which is the honest failure, but it is a failure you would be the first to see.

**Two R2 classes are one bucket:**

> Two Cloudflare R2 file classes in one organisation are the same store. Emseapea sets up one file store per organisation and environment, so a second class is another name for the same place rather than a separate one. Each app still keeps its files in its own folder there and reaches only that folder — your gateway puts the folder in front of every file an app asks for, and refuses anything outside it.

So if you want a genuine separation between two kinds of file — a different bucket, a different account, a different country — the second one has to be storage you set up yourself, which brings you to the next section and its caveats.

## Amazon S3 and Azure Blob Storage — names on a list

You create the bucket or container yourself, in your own account, with whatever access policy your organization requires.

**There is nowhere in Emseapea to enter a credential for either**, and that is not an oversight — nothing would read it. Choosing "Amazon S3" on a storage class records a decision about where an app's files are meant to live. It creates nothing, reaches nothing, and hands nothing to the app.

> **The trap worth knowing about.** When you deploy your gateway, a storage class on S3 or Azure Blob is skipped silently. The deploy reports no problem and the audit record looks exactly like one where a Cloudflare R2 store was set up and wired correctly. There is nothing on that response to tell the two apart. If you define an S3 or Azure Blob files class, write down that you did, because the deploy will not remind you.

If you need files in your own AWS or Azure account today, the honest arrangement is: create the storage, record the class so approvers can see where the data is meant to go, and give the app its access by a route outside Emseapea — and know that this is outside what the gateway can see or revoke.

## The four databases

Emseapea has no database provisioner. For every one of these you create the database yourself and, following the [machine-credentials rule](/setting-up-your-accounts/accounts.md#machine-credentials-only--never-a-personal-login), a **dedicated role for the app** — not your own database login, and not the superuser.

What happens next depends on which of the two routes the class is set to. The choice is explained in full under [How an app reaches a database](/admin-guide/storage.md#how-an-app-reaches-a-database); here is what each one needs from you.

### Straight to the database — this works today

1. Create the database, in your own provider account.
2. Create a role for the app with the narrowest rights that let it do its job, and a strong generated password. One role per app is better than one shared role, because revoking it then affects one app.
3. Restrict where it can connect from, if your provider supports that.
4. Assemble the connection string.
5. **Where it goes:** the storage class, on Settings → Storage. Emseapea encrypts it, and hands it to the app as `DATABASE_URL` when the app is deployed. If no encryption key is configured, the save is refused outright rather than stored in the clear.

**You end up with:** a database, a role that belongs to an app rather than a person, and a connection string Emseapea holds encrypted.

**What you give up** is visibility, and that is the bigger cost rather than the password:

> This app holds a database password.

The app connects itself, so its database activity passes through nothing of ours and **cannot appear on the dependency graph.** You can see what the app was granted; you can never see what it used.

### Through your gateway — recorded, not yet serving

Only Cloudflare D1 and Neon Postgres can offer this route at all — the gateway forwards web requests, and Amazon RDS and Azure Database for PostgreSQL do not answer over the web, so Emseapea refuses that pairing rather than recording an arrangement nothing could deliver.

And for the two that can, the product says on the screen:

> Not set up yet: Emseapea creates a shared file store and routes apps to it, but it does not yet put a database behind your gateway. This records how you have decided apps should reach it.

**Status: not built yet.** A class set this way records the arrangement you have chosen; a call from an app to that address is refused. Do not create a D1 or Neon credential for this route expecting a builder to be able to use it — tell your builders it is not something to build against yet.

## Three things no account of yours will fix

These apply to every provider on the list, including the one Emseapea creates. They are recorded here because each of them looks, on the screen, like something that is working.

**A storage class's region is written down and applied nowhere.**

> Recorded for your records, and not yet applied to anything. Emseapea does not turn these words into a provider location — a Cloudflare R2 file store is created wherever Cloudflare puts it, rather than in a region guessed from this box. Everywhere else on this list is somewhere you set up yourself, in whatever region you chose then.

If jurisdiction is load-bearing for you, create that storage yourself in the region you need and use the field to record what you did. And note that the caveat above appears on the Storage screen, not on the approval card — an approver reads "Kept in: United Kingdom" as a plain line.

**Nothing measures a size limit.** A cap is recorded so an approver can see the intended ceiling:

> Recorded so an approver can see the intended ceiling. Emseapea checks each app against it daily where it can read what that app is using, and says so plainly where it cannot rather than showing you a zero. Nothing is ever turned away at this number: it is a warning to act on, not something your storage itself keeps to.

In practice **"where it can read it" is nowhere today** — every app, every place, every day reads back "Not available", and the daily job that asks the question is not switched on in any environment either. That is deliberately not shown as a zero:

> Not available means nobody could read this figure — not that this app is using nothing. Treat it as a question still to be answered.

For a Cloudflare R2 store the reason is a design decision rather than a bug: the key went straight to your gateway and was never written down, so Emseapea cannot open the store to measure it. For everything else, Emseapea holds no account at all. Your provider's own console has the figure.

**Nothing deletes any bytes, ever.** Every storage class must have a rule for what happens when an app using it is shut down, and an app whose storage has no rule cannot be shut down at all. But the rule schedules a decision, not a deletion: the last step is listed as a task for a named administrator, with the exact folder to delete. Read "keep for 90 days, then delete" as "remind me, with the folder name, on day 90". No credential you supply changes this — Emseapea holds no key to your storage and, for R2, deliberately kept none.

## Where to go next

* [Somewhere for apps to keep things](/admin-guide/storage.md) — the whole Storage screen, including retention rules and what the export actually is.
* [Storing files and data in your app](/builder-guide/storing-files-and-data.md) — what your builders are handed once your list exists.
