From 6c428be78fabf9f90332a4acf0abb0abe0d4f95e Mon Sep 17 00:00:00 2001 From: Marcelo Soares Date: Thu, 16 Jul 2026 00:07:11 -0300 Subject: [PATCH 1/5] docs: Document embedded PostgreSQL --- .../02-database/01-connection.md | 124 +++++++++++++++++- .../lookups/configuration-reference.md | 2 +- 2 files changed, 119 insertions(+), 7 deletions(-) diff --git a/docs/06-concepts/03-data-and-the-database/02-database/01-connection.md b/docs/06-concepts/03-data-and-the-database/02-database/01-connection.md index 9332e54b..2c860c4c 100644 --- a/docs/06-concepts/03-data-and-the-database/02-database/01-connection.md +++ b/docs/06-concepts/03-data-and-the-database/02-database/01-connection.md @@ -1,12 +1,12 @@ --- -description: The database connection is defined in Serverpod's configuration and password files, with support for custom Postgres or SQLite instances. +description: Configure Serverpod database connections for embedded PostgreSQL, external PostgreSQL, and SQLite, including passwords and connection pools. --- # Connection -In Serverpod the connection details and password for the database are stored inside the `config` directory in your server package. Serverpod automatically establishes a connection to the database instance by using these configuration details when you start the server. +In Serverpod, the connection details and password for the database are stored inside the `config` directory in your server package. Serverpod automatically establishes a connection to the database instance by using these configuration details when you start the server. -If using Postgres, the easiest way to get started is to use a Docker container to run your local Postgres server, and this is how Serverpod is set up out of the box. This page contains more detailed information if you want to connect to another database instance or run Postgres locally yourself. +New projects use an embedded PostgreSQL database for development and testing. You can instead connect to PostgreSQL running in Docker or on another host, or use SQLite. ### Connection details @@ -42,7 +42,7 @@ Note that the same database backend must be used for all run modes. For more inf #### Configure search paths -If using Postgres, you can customize the search paths for your database connection—helpful if you're working with multiple schemas. By default, Postgres uses the `public` schema unless otherwise specified. +If using Postgres, you can customize the search paths for your database connection. This is helpful if you're working with multiple schemas. By default, Postgres uses the `public` schema unless otherwise specified. To override this, use the optional `searchPaths` setting in your configuration: @@ -108,9 +108,121 @@ development: No database password is required when using SQLite. -## Development database +## Use embedded PostgreSQL -A newly created Serverpod project has a preconfigured Docker instance with a Postgres database set up. Run the following command from the root of the `server` package to start the database: +Embedded PostgreSQL runs a real PostgreSQL server as a child process of your Serverpod server. It is intended for local development and testing, where it provides the same PostgreSQL dialect without requiring Docker or a separately installed database server. + +Set `dataPath` in the database section of `config/development.yaml`: + +```yaml +database: + host: localhost + port: 8090 + name: my_project + user: postgres + dataPath: .serverpod/development/pgdata +``` + +Keep the other PostgreSQL settings in place. Serverpod uses `name` and `user` when it creates the embedded cluster, and reads the database password from `config/passwords.yaml`. Once `dataPath` is set, Serverpod starts the embedded database before opening its connection pool. + +A relative `dataPath` is resolved from the root of the server package. Use a different directory for each run mode, for example `.serverpod/test/pgdata` in `config/test.yaml`. Keep these directories out of version control because they contain the complete local database cluster. + +On the first start, Serverpod downloads the PostgreSQL binaries for the current operating system and architecture into a per-user cache: + +- Linux: `$XDG_CACHE_HOME/serverpod`, or `~/.cache/serverpod` when `XDG_CACHE_HOME` is not set. +- macOS: `~/Library/Caches/serverpod`. +- Windows: `%LOCALAPPDATA%\serverpod\Cache`. + +Later projects and starts reuse that cache. The package supports Linux on x64 and Arm64, macOS on x64 and Arm64, and Windows on x64. Other targets throw `UnsupportedPlatformException` before initialization. + +The database files under `dataPath` persist when the server stops, so your development data remains available on the next start. Serverpod also repairs stale process metadata when possible after an unclean shutdown. + +Serverpod connects to its embedded database through a Unix domain socket by default. This avoids reserving a TCP port and lets several projects run without port conflicts. If another Serverpod process already manages the same `dataPath`, the new process attaches to the running database instead of starting another PostgreSQL process. + +The `SERVERPOD_DATABASE_DATA_PATH` environment variable overrides `database.dataPath` like other Serverpod configuration variables. Remove `dataPath` and the environment variable to return to the external PostgreSQL connection described by `host` and `port`. + +Use embedded PostgreSQL only for development and testing. For staging and production, connect Serverpod to a managed or separately operated PostgreSQL instance. The embedded package does not provide backups, replication, high availability, or production process supervision. + +### Reset the embedded database + +To start with an empty database, stop the Serverpod server and delete the directory configured by `dataPath`. Serverpod creates a fresh PostgreSQL cluster the next time it starts. + +:::warning + +Deleting `dataPath` permanently deletes the database and all local data stored in it. + +::: + +### Use the package directly + +Most Serverpod projects should configure `dataPath` and let Serverpod manage the database lifecycle. Use the `serverpod_embedded_postgres` package directly when a Dart tool or test harness needs its own PostgreSQL process. + +Add direct dependencies on the embedded package and the PostgreSQL client package: + +```bash +dart pub add serverpod_embedded_postgres postgres +``` + +Start the database, connect through the returned endpoint, and stop it when the process no longer needs it: + +```dart +import 'dart:io'; + +import 'package:postgres/postgres.dart'; +import 'package:serverpod_embedded_postgres/serverpod_embedded_postgres.dart'; + +Future main() async { + final postgres = await EmbeddedPostgres.start( + EmbeddedPostgresOptions( + dataDir: Directory('.serverpod/tool/pgdata'), + databaseName: 'tool_database', + ), + ); + + try { + final connection = await Connection.open(postgres.endpoint); + try { + await connection.execute('SELECT 1'); + } finally { + await connection.close(); + } + } finally { + await postgres.stop(); + } +} +``` + +The default `UnixTransport` uses a Unix domain socket. Use `TcpTransport` when another process or tool must connect over TCP: + +```dart +final postgres = await EmbeddedPostgres.start( + EmbeddedPostgresOptions( + dataDir: Directory('.serverpod/tool/pgdata'), + databaseName: 'tool_database', + transport: const TcpTransport(port: 0), + ), +); + +print(postgres.connectionString); +``` + +Port `0` selects an available loopback port. The handle also exposes `connectionUri`, `endpoint`, `version`, `pid`, and `isRunning`. + +Set `detach: true` in `EmbeddedPostgresOptions` only when the PostgreSQL process must survive after the Dart process exits. A later process can recover the handle with `EmbeddedPostgres.attach(dataDir)`. Detached processes require explicit lifecycle management. + +For CI environments that cannot download binaries while tests run, pre-populate the binary cache: + +```bash +dart run serverpod_embedded_postgres:prefetch +``` + +All package errors implement the sealed `EmbeddedPostgresException` type. Specific errors distinguish download and verification failures, unsupported platforms, initialization failures, startup timeouts, crashes, attachment failures, busy clusters, and incompatible PostgreSQL data directories. + +Calling `stop()` leaves `dataDir` intact. Calling `reset()` stops PostgreSQL and deletes the cluster, its run directory, and its logs before a later start initializes a new cluster. + +## Use PostgreSQL with Docker + +Serverpod projects include a Docker Compose configuration that you can use instead of embedded PostgreSQL. Remove `dataPath` from the selected run-mode configuration, then run the following command from the root of the server package: ```bash $ docker compose up --build --detach diff --git a/docs/06-concepts/lookups/configuration-reference.md b/docs/06-concepts/lookups/configuration-reference.md index b7007360..775fb861 100644 --- a/docs/06-concepts/lookups/configuration-reference.md +++ b/docs/06-concepts/lookups/configuration-reference.md @@ -47,7 +47,7 @@ Ports, hosts, and connection settings for the API, Insights, and web servers, th | SERVERPOD_DATABASE_MAX_CONNECTION_COUNT | database.maxConnectionCount | 10 | The maximum number of connections in the database pool. Set to 0 or a negative value for unlimited connections. | | SERVERPOD_DATABASE_FILE_PATH | database.filePath | - | The SQLite database file path. Set this instead of host/port/name/user when using SQLite. | | SERVERPOD_DATABASE_DIALECT | database.dialect | postgres | The database dialect. Valid options are `postgres` and `sqlite`. | -| SERVERPOD_DATABASE_DATA_PATH | database.dataPath | - | Directory for the embedded PostgreSQL cluster. When set, the server boots a managed Postgres before connecting. PostgreSQL only; ignored for SQLite. | +| SERVERPOD_DATABASE_DATA_PATH | database.dataPath | - | Directory for the embedded PostgreSQL cluster, relative to the server package unless absolute. When set, Serverpod starts or attaches to the cluster before connecting. PostgreSQL only; ignored for SQLite. | | SERVERPOD_REDIS_HOST | redis.host | - | The host address of the Redis server | | SERVERPOD_REDIS_PORT | redis.port | - | The port number for the Redis server | | SERVERPOD_REDIS_USER | redis.user | - | The user name for Redis authentication | From 30751b12e096c9a71bda9bb87c0e4d51afc28ca8 Mon Sep 17 00:00:00 2001 From: Marcelo Soares Date: Tue, 21 Jul 2026 15:41:02 -0300 Subject: [PATCH 2/5] docs: Restructure the embedded PostgreSQL section Break the section into subsections instead of a run of paragraphs, point at the configuration page rather than repeating what dataPath does, phrase the recovery and transport behavior in terms of what the reader observes, and use noun-shaped section titles like the rest of the page. --- .../02-database/01-connection.md | 58 ++++++++++--------- 1 file changed, 31 insertions(+), 27 deletions(-) diff --git a/docs/06-concepts/03-data-and-the-database/02-database/01-connection.md b/docs/06-concepts/03-data-and-the-database/02-database/01-connection.md index 2c860c4c..f7eb6617 100644 --- a/docs/06-concepts/03-data-and-the-database/02-database/01-connection.md +++ b/docs/06-concepts/03-data-and-the-database/02-database/01-connection.md @@ -108,11 +108,11 @@ development: No database password is required when using SQLite. -## Use embedded PostgreSQL +## Embedded PostgreSQL -Embedded PostgreSQL runs a real PostgreSQL server as a child process of your Serverpod server. It is intended for local development and testing, where it provides the same PostgreSQL dialect without requiring Docker or a separately installed database server. +Embedded PostgreSQL runs a real PostgreSQL server as a child process of your Serverpod server, so local development and testing get the same PostgreSQL dialect as production without Docker or a separately installed database. -Set `dataPath` in the database section of `config/development.yaml`: +New projects already enable it in the `development` and `test` run modes through the `dataPath` setting: ```yaml database: @@ -123,41 +123,45 @@ database: dataPath: .serverpod/development/pgdata ``` -Keep the other PostgreSQL settings in place. Serverpod uses `name` and `user` when it creates the embedded cluster, and reads the database password from `config/passwords.yaml`. Once `dataPath` is set, Serverpod starts the embedded database before opening its connection pool. +Leave the other PostgreSQL settings in place. Serverpod uses `name` and `user` when it creates the cluster and reads the password from `config/passwords.yaml`, the same as for an external instance. See [Database backends](../../server-fundamentals/configuration#database-backends) for how the setting fits into the rest of the configuration. -A relative `dataPath` is resolved from the root of the server package. Use a different directory for each run mode, for example `.serverpod/test/pgdata` in `config/test.yaml`. Keep these directories out of version control because they contain the complete local database cluster. +### Storage and platform support -On the first start, Serverpod downloads the PostgreSQL binaries for the current operating system and architecture into a per-user cache: +A relative `dataPath` is resolved from the root of the server package, and every run mode needs its own directory, for example `.serverpod/test/pgdata` in `config/test.yaml`. Each directory holds a complete PostgreSQL cluster, so keep it out of version control. + +The first start downloads the PostgreSQL binaries for the current operating system and architecture into a per-user cache, which every later start and every other project reuses: - Linux: `$XDG_CACHE_HOME/serverpod`, or `~/.cache/serverpod` when `XDG_CACHE_HOME` is not set. - macOS: `~/Library/Caches/serverpod`. - Windows: `%LOCALAPPDATA%\serverpod\Cache`. -Later projects and starts reuse that cache. The package supports Linux on x64 and Arm64, macOS on x64 and Arm64, and Windows on x64. Other targets throw `UnsupportedPlatformException` before initialization. - -The database files under `dataPath` persist when the server stops, so your development data remains available on the next start. Serverpod also repairs stale process metadata when possible after an unclean shutdown. +Binaries are available for Linux and macOS on x64 and Arm64, and for Windows on x64. On any other platform the server throws an `UnsupportedPlatformException` instead of starting. -Serverpod connects to its embedded database through a Unix domain socket by default. This avoids reserving a TCP port and lets several projects run without port conflicts. If another Serverpod process already manages the same `dataPath`, the new process attaches to the running database instead of starting another PostgreSQL process. +### Lifecycle and recovery -The `SERVERPOD_DATABASE_DATA_PATH` environment variable overrides `database.dataPath` like other Serverpod configuration variables. Remove `dataPath` and the environment variable to return to the external PostgreSQL connection described by `host` and `port`. +Serverpod starts the embedded database before it opens the connection pool, and connects to it over a Unix domain socket instead of a TCP port. That way several projects can run at the same time without competing for ports. When another Serverpod process already manages the same `dataPath`, the new process attaches to the running database rather than starting a second one. -Use embedded PostgreSQL only for development and testing. For staging and production, connect Serverpod to a managed or separately operated PostgreSQL instance. The embedded package does not provide backups, replication, high availability, or production process supervision. +The files under `dataPath` are kept when the server stops, so your development data is still there on the next start. If the server exits uncleanly, Serverpod clears the leftover process state on the next start and brings the database back up. -### Reset the embedded database +### Resetting the database -To start with an empty database, stop the Serverpod server and delete the directory configured by `dataPath`. Serverpod creates a fresh PostgreSQL cluster the next time it starts. +To start from an empty database, stop the Serverpod server and delete the directory configured by `dataPath`. Serverpod initializes a new PostgreSQL cluster the next time it starts. :::warning - Deleting `dataPath` permanently deletes the database and all local data stored in it. - ::: -### Use the package directly +### Moving to an external PostgreSQL + +Embedded PostgreSQL is for development and testing. It provides no backups, replication, high availability, or process supervision, so staging and production should connect to a managed or separately operated PostgreSQL instance. + +Remove `dataPath` from the run mode's configuration to connect to the `host` and `port` instead. The `SERVERPOD_DATABASE_DATA_PATH` [environment variable](../../lookups/configuration-reference) overrides the setting, so make sure it is unset as well. + +### Using the package directly -Most Serverpod projects should configure `dataPath` and let Serverpod manage the database lifecycle. Use the `serverpod_embedded_postgres` package directly when a Dart tool or test harness needs its own PostgreSQL process. +Configuring `dataPath` and letting Serverpod manage the lifecycle covers most projects. Use the `serverpod_embedded_postgres` package directly when a Dart tool or test harness needs a PostgreSQL process of its own. -Add direct dependencies on the embedded package and the PostgreSQL client package: +Add the embedded package and the PostgreSQL client package as direct dependencies: ```bash dart pub add serverpod_embedded_postgres postgres @@ -192,7 +196,7 @@ Future main() async { } ``` -The default `UnixTransport` uses a Unix domain socket. Use `TcpTransport` when another process or tool must connect over TCP: +The default transport is `UnixTransport`, which uses a Unix domain socket. Switch to `TcpTransport` when another process or tool has to connect over TCP: ```dart final postgres = await EmbeddedPostgres.start( @@ -206,23 +210,23 @@ final postgres = await EmbeddedPostgres.start( print(postgres.connectionString); ``` -Port `0` selects an available loopback port. The handle also exposes `connectionUri`, `endpoint`, `version`, `pid`, and `isRunning`. +Port `0` selects an available loopback port. Besides `connectionString`, the returned handle exposes `connectionUri`, `endpoint`, `version`, `pid`, and `isRunning`. -Set `detach: true` in `EmbeddedPostgresOptions` only when the PostgreSQL process must survive after the Dart process exits. A later process can recover the handle with `EmbeddedPostgres.attach(dataDir)`. Detached processes require explicit lifecycle management. +Set `detach: true` in `EmbeddedPostgresOptions` when the PostgreSQL process has to outlive the Dart process that started it. A later process picks the handle back up with `EmbeddedPostgres.attach(dataDir)`, and is then responsible for stopping it. -For CI environments that cannot download binaries while tests run, pre-populate the binary cache: +In CI environments that cannot download binaries while the tests run, fill the binary cache in a separate step: ```bash dart run serverpod_embedded_postgres:prefetch ``` -All package errors implement the sealed `EmbeddedPostgresException` type. Specific errors distinguish download and verification failures, unsupported platforms, initialization failures, startup timeouts, crashes, attachment failures, busy clusters, and incompatible PostgreSQL data directories. +Everything the package throws is an `EmbeddedPostgresException`. The type is sealed, so a `switch` over it covers every case: download and verification failures, unsupported platforms, initialization failures, startup timeouts, crashes, failed attachments, a cluster that is already busy, and an incompatible PostgreSQL data directory. -Calling `stop()` leaves `dataDir` intact. Calling `reset()` stops PostgreSQL and deletes the cluster, its run directory, and its logs before a later start initializes a new cluster. +Calling `stop()` leaves `dataDir` intact. Calling `reset()` stops PostgreSQL and deletes the cluster, its run directory, and its logs, so the next start initializes a new cluster. -## Use PostgreSQL with Docker +## PostgreSQL with Docker -Serverpod projects include a Docker Compose configuration that you can use instead of embedded PostgreSQL. Remove `dataPath` from the selected run-mode configuration, then run the following command from the root of the server package: +Serverpod projects include a Docker Compose configuration that you can use instead of embedded PostgreSQL. Remove `dataPath` from the selected run mode's configuration, then run the following command from the root of the server package: ```bash $ docker compose up --build --detach From a943d1e58b4a69e5a046c3025608dcaca4a17340 Mon Sep 17 00:00:00 2001 From: Marcelo Soares Date: Tue, 21 Jul 2026 17:15:10 -0300 Subject: [PATCH 3/5] docs: Move embedded PostgreSQL to a dedicated page Rewriting the connection page around the embedded database displaced the Docker instructions, which are still the alternative for anyone who wants to run Postgres themselves. Restore that page and give embedded PostgreSQL a short reference page of its own instead: what it is, how the dataPath setting turns it on, where the files live, what happens on start, how to reset it, and why it stays out of production. --- .../02-database/01-connection.md | 128 +----------------- .../02-database/17-embedded-postgres.md | 48 +++++++ 2 files changed, 54 insertions(+), 122 deletions(-) create mode 100644 docs/06-concepts/03-data-and-the-database/02-database/17-embedded-postgres.md diff --git a/docs/06-concepts/03-data-and-the-database/02-database/01-connection.md b/docs/06-concepts/03-data-and-the-database/02-database/01-connection.md index f7eb6617..d964abd5 100644 --- a/docs/06-concepts/03-data-and-the-database/02-database/01-connection.md +++ b/docs/06-concepts/03-data-and-the-database/02-database/01-connection.md @@ -1,12 +1,12 @@ --- -description: Configure Serverpod database connections for embedded PostgreSQL, external PostgreSQL, and SQLite, including passwords and connection pools. +description: The database connection is defined in Serverpod's configuration and password files, with support for custom Postgres or SQLite instances. --- # Connection -In Serverpod, the connection details and password for the database are stored inside the `config` directory in your server package. Serverpod automatically establishes a connection to the database instance by using these configuration details when you start the server. +In Serverpod the connection details and password for the database are stored inside the `config` directory in your server package. Serverpod automatically establishes a connection to the database instance by using these configuration details when you start the server. -New projects use an embedded PostgreSQL database for development and testing. You can instead connect to PostgreSQL running in Docker or on another host, or use SQLite. +New projects run an [embedded PostgreSQL](./embedded-postgres) in development and testing, which Serverpod manages for you. This page covers the alternatives: running Postgres in Docker, and connecting to an instance you host yourself. ### Connection details @@ -42,7 +42,7 @@ Note that the same database backend must be used for all run modes. For more inf #### Configure search paths -If using Postgres, you can customize the search paths for your database connection. This is helpful if you're working with multiple schemas. By default, Postgres uses the `public` schema unless otherwise specified. +If using Postgres, you can customize the search paths for your database connection—helpful if you're working with multiple schemas. By default, Postgres uses the `public` schema unless otherwise specified. To override this, use the optional `searchPaths` setting in your configuration: @@ -108,125 +108,9 @@ development: No database password is required when using SQLite. -## Embedded PostgreSQL +## Development database -Embedded PostgreSQL runs a real PostgreSQL server as a child process of your Serverpod server, so local development and testing get the same PostgreSQL dialect as production without Docker or a separately installed database. - -New projects already enable it in the `development` and `test` run modes through the `dataPath` setting: - -```yaml -database: - host: localhost - port: 8090 - name: my_project - user: postgres - dataPath: .serverpod/development/pgdata -``` - -Leave the other PostgreSQL settings in place. Serverpod uses `name` and `user` when it creates the cluster and reads the password from `config/passwords.yaml`, the same as for an external instance. See [Database backends](../../server-fundamentals/configuration#database-backends) for how the setting fits into the rest of the configuration. - -### Storage and platform support - -A relative `dataPath` is resolved from the root of the server package, and every run mode needs its own directory, for example `.serverpod/test/pgdata` in `config/test.yaml`. Each directory holds a complete PostgreSQL cluster, so keep it out of version control. - -The first start downloads the PostgreSQL binaries for the current operating system and architecture into a per-user cache, which every later start and every other project reuses: - -- Linux: `$XDG_CACHE_HOME/serverpod`, or `~/.cache/serverpod` when `XDG_CACHE_HOME` is not set. -- macOS: `~/Library/Caches/serverpod`. -- Windows: `%LOCALAPPDATA%\serverpod\Cache`. - -Binaries are available for Linux and macOS on x64 and Arm64, and for Windows on x64. On any other platform the server throws an `UnsupportedPlatformException` instead of starting. - -### Lifecycle and recovery - -Serverpod starts the embedded database before it opens the connection pool, and connects to it over a Unix domain socket instead of a TCP port. That way several projects can run at the same time without competing for ports. When another Serverpod process already manages the same `dataPath`, the new process attaches to the running database rather than starting a second one. - -The files under `dataPath` are kept when the server stops, so your development data is still there on the next start. If the server exits uncleanly, Serverpod clears the leftover process state on the next start and brings the database back up. - -### Resetting the database - -To start from an empty database, stop the Serverpod server and delete the directory configured by `dataPath`. Serverpod initializes a new PostgreSQL cluster the next time it starts. - -:::warning -Deleting `dataPath` permanently deletes the database and all local data stored in it. -::: - -### Moving to an external PostgreSQL - -Embedded PostgreSQL is for development and testing. It provides no backups, replication, high availability, or process supervision, so staging and production should connect to a managed or separately operated PostgreSQL instance. - -Remove `dataPath` from the run mode's configuration to connect to the `host` and `port` instead. The `SERVERPOD_DATABASE_DATA_PATH` [environment variable](../../lookups/configuration-reference) overrides the setting, so make sure it is unset as well. - -### Using the package directly - -Configuring `dataPath` and letting Serverpod manage the lifecycle covers most projects. Use the `serverpod_embedded_postgres` package directly when a Dart tool or test harness needs a PostgreSQL process of its own. - -Add the embedded package and the PostgreSQL client package as direct dependencies: - -```bash -dart pub add serverpod_embedded_postgres postgres -``` - -Start the database, connect through the returned endpoint, and stop it when the process no longer needs it: - -```dart -import 'dart:io'; - -import 'package:postgres/postgres.dart'; -import 'package:serverpod_embedded_postgres/serverpod_embedded_postgres.dart'; - -Future main() async { - final postgres = await EmbeddedPostgres.start( - EmbeddedPostgresOptions( - dataDir: Directory('.serverpod/tool/pgdata'), - databaseName: 'tool_database', - ), - ); - - try { - final connection = await Connection.open(postgres.endpoint); - try { - await connection.execute('SELECT 1'); - } finally { - await connection.close(); - } - } finally { - await postgres.stop(); - } -} -``` - -The default transport is `UnixTransport`, which uses a Unix domain socket. Switch to `TcpTransport` when another process or tool has to connect over TCP: - -```dart -final postgres = await EmbeddedPostgres.start( - EmbeddedPostgresOptions( - dataDir: Directory('.serverpod/tool/pgdata'), - databaseName: 'tool_database', - transport: const TcpTransport(port: 0), - ), -); - -print(postgres.connectionString); -``` - -Port `0` selects an available loopback port. Besides `connectionString`, the returned handle exposes `connectionUri`, `endpoint`, `version`, `pid`, and `isRunning`. - -Set `detach: true` in `EmbeddedPostgresOptions` when the PostgreSQL process has to outlive the Dart process that started it. A later process picks the handle back up with `EmbeddedPostgres.attach(dataDir)`, and is then responsible for stopping it. - -In CI environments that cannot download binaries while the tests run, fill the binary cache in a separate step: - -```bash -dart run serverpod_embedded_postgres:prefetch -``` - -Everything the package throws is an `EmbeddedPostgresException`. The type is sealed, so a `switch` over it covers every case: download and verification failures, unsupported platforms, initialization failures, startup timeouts, crashes, failed attachments, a cluster that is already busy, and an incompatible PostgreSQL data directory. - -Calling `stop()` leaves `dataDir` intact. Calling `reset()` stops PostgreSQL and deletes the cluster, its run directory, and its logs, so the next start initializes a new cluster. - -## PostgreSQL with Docker - -Serverpod projects include a Docker Compose configuration that you can use instead of embedded PostgreSQL. Remove `dataPath` from the selected run mode's configuration, then run the following command from the root of the server package: +A newly created Serverpod project has a preconfigured Docker instance with a Postgres database set up. To use it instead of the [embedded PostgreSQL](./embedded-postgres), remove `dataPath` from the run mode's configuration and run the following command from the root of the `server` package to start the database: ```bash $ docker compose up --build --detach diff --git a/docs/06-concepts/03-data-and-the-database/02-database/17-embedded-postgres.md b/docs/06-concepts/03-data-and-the-database/02-database/17-embedded-postgres.md new file mode 100644 index 00000000..035fb6f0 --- /dev/null +++ b/docs/06-concepts/03-data-and-the-database/02-database/17-embedded-postgres.md @@ -0,0 +1,48 @@ +--- +description: Embedded PostgreSQL is a real PostgreSQL server that Serverpod starts and stops with your server, for local development and testing without Docker. +--- + +# Embedded PostgreSQL + +New projects run an embedded PostgreSQL in the `development` and `test` run modes. It is a real PostgreSQL server that Serverpod starts and stops together with your server, so local development gets the same database engine as production without installing PostgreSQL or running Docker. + +It is meant for local development and testing only. There are no backups, no replication, and nothing supervising the process, so staging and production connect to a managed or separately operated PostgreSQL instead. See [Connection](./connection) for those setups. + +## Enable it + +Embedded PostgreSQL is enabled by the `dataPath` setting, which generated projects already include: + +```yaml title="config/development.yaml" +database: + host: localhost + port: 8090 + name: myproject + user: postgres + dataPath: .serverpod/development/pgdata +``` + +The rest of the database settings stay as they are. Serverpod uses `name` and `user` when it creates the database and reads the password from `config/passwords.yaml`, exactly as it would for an external instance. Remove `dataPath` to connect to the `host` and `port` instead. + +A relative `dataPath` is resolved from the root of the server package, and each run mode needs its own directory, for example `.serverpod/test/pgdata` in `config/test.yaml`. The directory holds a complete database, so keep it out of version control. + +## What happens when the server starts + +The first start downloads the PostgreSQL binaries for your operating system and architecture into a per-user cache, which every later start and every other project reuses. Binaries are available for Linux and macOS on x64 and Arm64, and for Windows on x64. + +Serverpod starts the database before it opens its connection pool, and connects over a Unix domain socket instead of a TCP port, so several projects can run at once without competing for ports. If another Serverpod process already runs a database in the same `dataPath`, the new process attaches to it rather than starting a second one. + +The files under `dataPath` are kept when the server stops, so your data is still there on the next start. After an unclean exit, Serverpod clears the leftover process state and brings the database back up. + +## Reset the database + +To start from an empty database, stop the server and delete the directory `dataPath` points at. Serverpod creates a new one on the next start. + +:::warning +Deleting `dataPath` permanently deletes the database and all local data stored in it. +::: + +## Related + +- [Connection](./connection): connecting to a PostgreSQL instance you run yourself. +- [Configuration](../../server-fundamentals/configuration#database-backends): the database section of the run mode configuration. +- [serverpod_embedded_postgres](https://pub.dev/packages/serverpod_embedded_postgres): the package behind this, for tools that need a PostgreSQL process of their own. From 1296051348b1118dbfc14581217b0e8899a4ff64 Mon Sep 17 00:00:00 2001 From: Marcelo Soares Date: Tue, 21 Jul 2026 17:24:10 -0300 Subject: [PATCH 4/5] docs: Show how to reach the embedded database from a database tool The server talks to the embedded database over a Unix socket, so psql and pgAdmin cannot reach it while it runs that way. Point at 'serverpod database start', which serves the same database over TCP. --- .../02-database/17-embedded-postgres.md | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/docs/06-concepts/03-data-and-the-database/02-database/17-embedded-postgres.md b/docs/06-concepts/03-data-and-the-database/02-database/17-embedded-postgres.md index 035fb6f0..745ed26c 100644 --- a/docs/06-concepts/03-data-and-the-database/02-database/17-embedded-postgres.md +++ b/docs/06-concepts/03-data-and-the-database/02-database/17-embedded-postgres.md @@ -33,6 +33,22 @@ Serverpod starts the database before it opens its connection pool, and connects The files under `dataPath` are kept when the server stops, so your data is still there on the next start. After an unclean exit, Serverpod clears the leftover process state and brings the database back up. +## Connect a database tool + +`psql`, pgAdmin, and most other database clients connect over TCP, not the Unix socket the server uses. To inspect the data with one of them, start the database on its own while the server is stopped: + +```bash +$ serverpod database start +``` + +It boots the database configured for the `development` run mode and keeps it listening on the configured port until you stop it with Ctrl+C. Connect with the `name` and `user` from that run mode's configuration, and the password from `config/passwords.yaml`. + +Pass `--mode` to pick another run mode and `--port` to listen somewhere else: + +```bash +$ serverpod database start --mode test --port 9090 +``` + ## Reset the database To start from an empty database, stop the server and delete the directory `dataPath` points at. Serverpod creates a new one on the next start. @@ -45,4 +61,5 @@ Deleting `dataPath` permanently deletes the database and all local data stored i - [Connection](./connection): connecting to a PostgreSQL instance you run yourself. - [Configuration](../../server-fundamentals/configuration#database-backends): the database section of the run mode configuration. +- [`serverpod database`](../../cli/commands/database): every option of the command above. - [serverpod_embedded_postgres](https://pub.dev/packages/serverpod_embedded_postgres): the package behind this, for tools that need a PostgreSQL process of their own. From 36b74b4e0bae6f4f6a234e18c6cf4902c10f84ef Mon Sep 17 00:00:00 2001 From: Marcelo Soares Date: Tue, 21 Jul 2026 17:40:38 -0300 Subject: [PATCH 5/5] docs: Note that integration tests need no database of their own --- .../02-database/17-embedded-postgres.md | 12 +++++++++++- docs/06-concepts/08-testing/01-get-started.md | 2 +- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/docs/06-concepts/03-data-and-the-database/02-database/17-embedded-postgres.md b/docs/06-concepts/03-data-and-the-database/02-database/17-embedded-postgres.md index 745ed26c..ff70e57a 100644 --- a/docs/06-concepts/03-data-and-the-database/02-database/17-embedded-postgres.md +++ b/docs/06-concepts/03-data-and-the-database/02-database/17-embedded-postgres.md @@ -35,7 +35,7 @@ The files under `dataPath` are kept when the server stops, so your data is still ## Connect a database tool -`psql`, pgAdmin, and most other database clients connect over TCP, not the Unix socket the server uses. To inspect the data with one of them, start the database on its own while the server is stopped: +Most clients like `psql` and `pgAdmin` connect over TCP, not the Unix socket the server uses. To inspect the data with one of them, start the database on its own while the server is stopped: ```bash $ serverpod database start @@ -49,6 +49,16 @@ Pass `--mode` to pick another run mode and `--port` to listen somewhere else: $ serverpod database start --mode test --port 9090 ``` +## Run integration tests + +Integration tests bring their own database, so there is nothing to install or start first: + +```bash +$ dart test +``` + +Each test gets an isolated temporary data directory that is deleted on teardown, so tests cannot see each other's data or leave anything behind between runs. See [Get started with testing](../../testing/get-started) for the rest of the setup. + ## Reset the database To start from an empty database, stop the server and delete the directory `dataPath` points at. Serverpod creates a new one on the next start. diff --git a/docs/06-concepts/08-testing/01-get-started.md b/docs/06-concepts/08-testing/01-get-started.md index 6b17e8c9..0a5abe3c 100644 --- a/docs/06-concepts/08-testing/01-get-started.md +++ b/docs/06-concepts/08-testing/01-get-started.md @@ -214,7 +214,7 @@ The location of the test tools can be changed by changing the `server_test_tools ::: -Before the test can be run the Postgres and Redis also have to be started: +The test server runs an [embedded PostgreSQL](../data-and-the-database/database/embedded-postgres) in a temporary directory that is removed afterwards, so there is no database to start first. If you removed `dataPath` from `config/test.yaml` to run Postgres yourself, or your tests need Redis, start those services before the tests: ```bash docker compose up --build --detach