Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,8 @@ That is the whole mental model: you work in the server and the app, and Serverpo
myproject/
├── pubspec.yaml # Workspace root: one `dart pub get` resolves all packages
├── AGENTS.md # Instructions for AI agents working in the project
├── .github/ # CI workflows: analyze, format, and test
├── .github/ # CI workflows: analyze, format, test, and deploy to Serverpod Cloud
├── .vscode/ # Attach-to-server debug configs and a serverpod start task, plus mcp.json if you picked VS Code
├── CLAUDE.md # If you picked Claude: loads AGENTS.md for Claude
├── .mcp.json, .claude/ # If you picked Claude: MCP config and skills
├── .cursor/ # If you picked Cursor: MCP config and skills
├── .codex/ # If you picked Codex: MCP config
Expand Down Expand Up @@ -55,7 +54,7 @@ myproject/
└── assets/config.json # The server URL the app reads at startup
```

The exact set depends on your create-time choices: the auth endpoints and sign-in screen come with authentication, the web pieces with the web server option, and the MCP configs and skills with the editors you picked. `AGENTS.md` is always created, and `CLAUDE.md` only when you pick Claude.
The exact set depends on your create-time choices: the auth endpoints and sign-in screen come with authentication, the web pieces with the web server option, and the MCP configs and skills with the editors you picked. `AGENTS.md` is always created.

</p>
</details>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ Outside `serverpod start`, the server is a plain Dart program you can run yourse
dart run bin/main.dart --apply-migrations
```

The server accepts arguments that control how it starts: `--mode` selects the run mode, `--role` selects the [server role](#choose-a-server-role), and `--apply-migrations` applies pending migrations during startup. Without `--apply-migrations`, the server still checks the database schema at startup. On a mismatch, it exits with code 1 in the `development` run mode and logs a warning in other run modes. See the [run options reference](../lookups/configuration-reference#run-options) for the full list, and the [Deploy](../../deployments/deploy-to-serverpod-cloud) section for running in production.
The server accepts arguments that control how it starts: `--mode` selects the run mode, `--role` selects the [server role](#choose-a-server-role), and `--apply-migrations` applies pending migrations during startup. Without `--apply-migrations`, the server still checks the database schema at startup. On a mismatch, it logs a warning and keeps running. See the [run options reference](../lookups/configuration-reference#run-options) for the full list, and the [Deploy](../../deployments/deploy-to-serverpod-cloud) section for running in production.

## Choose a server role

Expand Down
15 changes: 2 additions & 13 deletions docs/06-concepts/01-server-fundamentals/03-configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -93,10 +93,10 @@ The three server blocks configure Serverpod's three servers: the API server your

### Database backends

Serverpod supports both PostgreSQL and SQLite as database backends.
Serverpod supports both PostgreSQL and SQLite as database backends. A server that does not use a database leaves the `database` section out of every run mode file, and `serverpod generate` then skips table code and migrations.

:::warning
All run modes must use the same database backend: creating migrations fails otherwise. This also keeps your development environment consistent with production.
All run modes must use the same database backend, and either all of them or none of them configure a database: `serverpod generate` fails otherwise. This also keeps your development environment consistent with production.
:::

#### PostgreSQL
Expand Down Expand Up @@ -320,17 +320,6 @@ extraClasses:

See the [serialization documentation](../data-and-the-database/models/custom-serialization) for implementing custom serializable classes.

### Features

Control which Serverpod features are enabled:

```yaml
features:
database: false
```

A server that does not use a database can set `database: false` to skip migrations and table generation. Projects created without a database, for example with `--no-database`, don't include this setting, so add it yourself.

### Experimental features

Experimental features are off by default and opted into per project with the `experimental_features` key. The current one is `databaseSync`, which enables [`database: sync`](../data-and-the-database/database/client-side-database#sync-tables-with-the-server) on table models; `all` enables every available feature:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -124,10 +124,7 @@ To apply migrations explicitly, start the server runtime with the `--apply-migra
$ dart run bin/main.dart --apply-migrations
```

If a migration fails, or the database doesn't match the latest migration afterward, the outcome depends on the run mode:

- **Any run mode except `development`:** the server logs `Failed to apply database migrations.` or `Database does not match target state.` and keeps starting.
- **`development`:** the server exits with code 1.
If a migration fails, or the database doesn't match the latest migration afterward, the server logs `Failed to apply database migrations.` or `Database does not match target state.` and keeps starting. Requests that use the mismatched tables can fail until you fix the schema.

Migrations can also be applied with the [maintenance role](../../server-fundamentals/running-your-server#choose-a-server-role). The server applies the migrations and then exits, which suits CI jobs and other automated processes. If a migration fails, or the database doesn't match the latest migration afterward, it exits with code 1 in every run mode, so the job fails.

Expand Down
2 changes: 1 addition & 1 deletion docs/06-concepts/08-testing/01-get-started.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ That means no separate server to start, no HTTP client to write, and no mocked d

Two things follow from that:

- **Tests stay independent.** Anything a test writes to the database is rolled back once that test finishes, so tests never see each other's data and you do not clean up after yourself. Each `withServerpod` group also runs against its own temporary database, which is dropped when the group finishes.
- **Tests stay independent.** Anything a test writes to the database is rolled back once that test finishes, so tests never see each other's data and you do not clean up after yourself. By default, each `withServerpod` group also runs against its own temporary database, which is dropped when the group finishes.
- **Each test sets its own scene.** A session builder decides what the server state looks like for a call, such as who is signed in.

## Set up
Expand Down
21 changes: 18 additions & 3 deletions docs/06-concepts/08-testing/03-configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ withServerpod(
| `configOverride` | A function that changes values in the loaded config before the server starts. | `null` |
| `databaseInterceptor` | A [database interceptor](../data-and-the-database/database/database-interceptors) for the test server to use. | `null` |
| `enableSessionLogging` | Whether session logging is on. | `false` |
| `ephemeralDatabase` | Whether the group gets its own empty database. See [below](#ephemeraldatabase). | `true` |
| `experimentalFeatures` | Experimental features to enable, such as [diagnostic event handlers](../operations/exception-monitoring). | `null` |
| `rollbackDatabase` | When database changes are rolled back. See [below](#rollbackdatabase). | `RollbackDatabase.afterEach` |
| `runMode` | The run mode the server starts in. | `test` |
Expand All @@ -37,9 +38,7 @@ withServerpod(
| `testServerOutputMode` | How much server output reaches your terminal. See [below](#server-output). | `TestServerOutputMode.normal` |

:::note
When `config/generator.yaml` sets `features: database: false`, the generated `withServerpod` has no `applyMigrations`, `databaseInterceptor`, `rollbackDatabase`, or `runtimeParametersBuilder` parameter, so passing one is a compile error. Rollback is off in that case and there is nothing to migrate.

Projects created without a database, for example with `--no-database`, don't include this setting, so add it and run `serverpod generate`.
When the run mode files configure no database, for example in a project created with `--no-database`, the generated `withServerpod` has no `applyMigrations`, `databaseInterceptor`, `ephemeralDatabase`, `rollbackDatabase`, or `runtimeParametersBuilder` parameter, so passing one is a compile error. Rollback is off in that case and there is nothing to migrate.
:::

Set `serverDirectory` when tests run from somewhere other than the server package, such as the workspace root. Without it the server resolves those paths against the current directory, misses your config, and falls over later on whatever it needed from it.
Expand All @@ -58,6 +57,22 @@ withServerpod(
);
```

## Use an existing database {#ephemeraldatabase}

Each `withServerpod` group runs against its own empty database, created when the group starts and dropped when it finishes. To run against the database configured for the run mode instead, for example one you seeded beforehand, pass `ephemeralDatabase: false`:

```dart
withServerpod(
'Given a seeded database',
(sessionBuilder, endpoints) {
/* test code */
},
ephemeralDatabase: false,
);
```

Serverpod then neither creates nor drops that database, and [`rollbackDatabase`](#rollbackdatabase) still decides whether the group's writes are rolled back. Groups that share the database can't run in parallel, so run their test files one at a time with `dart test --concurrency=1`.

## Database rollback {#rollbackdatabase}

By default each test runs inside a transaction that is rolled back when that test ends, so tests cannot see each other's data. Three values control this:
Expand Down
2 changes: 1 addition & 1 deletion docs/06-concepts/cli/commands/create/_create.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,4 @@ In an interactive terminal, `serverpod create` opens a setup screen where you ch

The `--database`, `--redis`, `--auth`, `--webapp`, `--website`, and `--ide` flags apply only when the setup screen does not open, for example with `--no-interactive` or in CI. Without the setup screen, the project also gets Redis configuration and editor setup for Claude, Cursor, and VS Code, unless you pass `--no-redis` or choose editors with `--ide`.

To create a project without a database, deselect **Database (recommended)** under **Database & caching** on the setup screen, or pass `--no-interactive --no-database`. The new project still has the generator's database feature on, so set `database: false` under [`features`](../../../01-server-fundamentals/03-configuration.md#features) in `config/generator.yaml`, then run `serverpod generate`.
To create a project without a database, deselect **Database (recommended)** under **Database & caching** on the setup screen, or pass `--no-interactive --no-database`. The new project's run mode files then have no `database` section, which is what turns off database code generation. See [Database backends](../../../01-server-fundamentals/03-configuration.md#database-backends).
1 change: 0 additions & 1 deletion docs/06-concepts/lookups/configuration-reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,6 @@ Options for `config/generator.yaml`, which configures `serverpod generate`.
| modules | map | - | Module dependencies with optional nicknames. |
| extraClasses | list | - | List of custom serializable classes to include in code generation. |
| serialize_as_jsonb_by_default | bool | false | When true, all serializable fields default to `jsonb` storage instead of `json`. |
| features | map | \{database: true\} | Feature flags. Currently only `database` is supported. |
| experimental_features | map | - | Experimental features. Available keys: `databaseSync` (enables `database: sync`) and `all`. |

## Related
Expand Down
1 change: 0 additions & 1 deletion docs/11-upgrading/01-upgrade-to-four.md
Original file line number Diff line number Diff line change
Expand Up @@ -275,7 +275,6 @@ In a folder that already has a Serverpod server, `serverpod create .` runs an up
- `<project>_server/docker-compose.yaml` and the workflows in `.github/workflows/`.
- The scaffolded authentication endpoints in `<project>_server/lib/src/auth/`, and the scaffolded web server files in `<project>_server/lib/src/web/` and `<project>_server/web/`.
- `lib/main.dart`, `lib/client.dart`, and `lib/screens/greetings_screen.dart` in your Flutter app.
- `CLAUDE.md`, which becomes a pointer to an `AGENTS.md` file that the command doesn't create.

The command also adds dependencies to your `pubspec.yaml` files. In an interactive terminal on a project that already has migrations, it only asks which editors to set up. In that case, it turns every other option off, so the rewritten files lose your setup.

Expand Down
Loading