# SQLite databases

An embedded SQLite database is a single file on a [volume](volumes.md) mounted into your app. There is no database server: your app opens the file directly, with no network latency and no connections to manage. It suits internal tools and other apps with modest write traffic. Nimbus Land copies every change off the volume as it happens, keeps 30 days of changes so you can restore to any moment in that window, and rebuilds the file from the copy if the volume is ever lost.

## Adding one

On the app's **Resources** tab, choose **Add dependency → Database**, then **SQLite (embedded)** as the **Engine**. Under **Storage**, either create a new volume (choose the **Database file name**, `app.db` by default, and the **Volume size (GB)**) or use a volume the app already has (enter an absolute **Database file path** under one of its mount paths). Then choose **Create SQLite database**.

A new volume is mounted at `/data`. Nimbus Land then sets these variables and redeploys the app:

```sh
DATABASE_URL=sqlite:///data/app.db
SQLITE_DB_PATH=/data/app.db
```

These are [managed variables](dependencies.md#managed-variables): you can rename them in the dialog or later under **Edit**, and they are removed when you remove the database. Laravel apps get `DB_URL` and `DB_DATABASE` by default.

## Pointing your framework at the file

`DATABASE_URL` uses the common `sqlite:///absolute/path` form. If your stack expects a different form, read `SQLITE_DB_PATH` or set your own variable:

| Stack | Setting |
|---|---|
| Rails | `DATABASE_URL=sqlite3:/data/app.db` |
| Prisma | `DATABASE_URL=file:/data/app.db` |
| Django, SQLAlchemy | `sqlite:////data/app.db` (four slashes) |
| Phoenix (Ecto) | `database: System.get_env("SQLITE_DB_PATH")` |

## What to know

- **One instance.** SQLite has a single writer, so an app with a SQLite database runs one instance and can't be scaled out. Each deploy stops the old instance before starting the new one, so there is a short gap instead of a rolling update. To run several instances, use managed Postgres.
- **Run migrations as the release command.** Set the release command on the app's **Deployments** tab (for example `bin/rails db:migrate`). It runs with the volume mounted, as the only writer. Don't run migrations against the same file from a separate one-off run.
- **Production only.** Staging and preview environments mount no volumes, so they start with a fresh, empty database file each time.
- **One SQLite database per app.** For more databases, or a database shared by several apps, use managed Postgres.

## Backups and restore

Every change is copied off the volume, within about a second, to storage dedicated to your app, and 30 days of changes are kept. The **Data protection** section of the database's Edit dialog shows when the last change was copied, how far back you can restore, and the latest restore test. It warns you when a running app has had no copy for 26 hours (**Backups behind**), and when a restore test failed or some changes are missing from the copies (**Backups need attention**).

**Restore to a point in time.** Choose **Restore to a point in time** in the Data protection section, pick a moment (in UTC) inside the window, and confirm. Your app restarts, about as long as a deploy takes, and comes back on the database as it was at that moment. The file it replaced is kept on the same volume, next to the database, as `app.db.before-restore-<time>`, so you can go back to it. If the restore can't be completed, your app starts on its original database, unchanged, and the section says why. After a restore, the window starts again at the restore. Restoring needs both the **Manage apps** and **Manage storage** permissions.

**Automatic rebuild.** If the app starts and the database file is missing (a lost or replaced volume), the file is rebuilt from the copy before your app starts.

**Checked, not just copied.** Every restore and rebuild runs SQLite's integrity check before your app starts, and once a day Nimbus Land restores the latest copy on the side and checks it, without touching your app.

The volume's own [snapshots](volumes.md#snapshots) also cover the file.

## Removing the database

Open **Edit** on the database's entry:

- **Remove** disconnects the database and removes its variables, but keeps the volume, the file and its backups.
- **Delete** removes all three. It asks you to type the app's name first and cannot be undone.
