Automatic PostgreSQL Provisioning in Quarkus with Dev Services
Quarkus Dev Services can start a PostgreSQL container automatically in dev and test mode, eliminating manual database setup. Learn the prerequisites, configuration, and verification steps.
08 Aug 2025, 21:21 UTC

The problem: manual PostgreSQL setup interrupts development flow
Setting up a local PostgreSQL instance for every Quarkus project introduces repetitive work: install the server, create a database, manage credentials, and clean state between test runs. When the database is external, integration tests also depend on a running service, which makes onboarding and continuous integration harder.
Quarkus Dev Services removes this friction for development and testing. When your application includes a PostgreSQL JDBC driver and no production database URL is configured, Quarkus can start a PostgreSQL container automatically in dev mode and during tests. You get an isolated, disposable database without manual Docker commands.
What Dev Services does
Dev Services is a Quarkus feature that uses Testcontainers—a Java library that manages Docker containers programmatically—to launch backing services on demand. For PostgreSQL, Quarkus starts a container, waits until the database accepts connections, and injects the resulting JDBC URL into your application. The container is ephemeral: it stops when the application or test run ends, and its data does not persist unless you explicitly configure a volume.
Prerequisites
- Quarkus 2.13 or later, or any 3.x release. Dev Services behavior and default image versions can vary between major releases, so verify the defaults for your version.
- JDK 11 or later.
- Maven or Gradle.
- A running container runtime such as Docker or Podman, because Testcontainers requires it to launch the PostgreSQL image.
- The PostgreSQL JDBC extension (
io.quarkus:quarkus-jdbc-postgresql) added to your project.
Configuring the project
Add the PostgreSQL extension to your build file. With Maven, add the dependency:
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-jdbc-postgresql</artifactId>
</dependency>
In src/main/resources/application.properties, declare the database kind. If you omit quarkus.datasource.jdbc.url, Quarkus treats the datasource as unconfigured for production and activates Dev Services in dev and test profiles:
quarkus.datasource.db-kind=postgresql
If your application uses Hibernate ORM, add quarkus.hibernate-orm.database.generation=drop-and-create so the schema is rebuilt on each container start. If you use Flyway instead, add quarkus.flyway.migrate-at-start=true and place migrations in src/main/resources/db/migration. Flyway migrations run automatically against the Dev Services container.
Starting the application in dev mode
Run the application from the project root:
./mvnw quarkus:dev
This command requires local user permissions to access the Docker daemon. On the first run, Quarkus downloads the configured PostgreSQL image, which may take time depending on your network. Subsequent runs reuse the cached image.
During startup, Quarkus checks for an explicit datasource URL. Finding none, it starts a PostgreSQL container through Testcontainers, waits for the database to become ready, and injects the connection details. Your application code does not change; it receives a standard javax.sql.DataSource.
Expected checks
Verify that Dev Services activated correctly:
- Console output: Look for a log line indicating that Dev Services started a PostgreSQL container. The message includes the dynamically assigned port, which is not the default 5432.
- Datasource URL: In dev mode, open the Dev UI or check the configuration sources. The active JDBC URL should point to
localhostwith a random high port, not a fixed production host. - Integration test: Write a test that injects the datasource and executes a simple query. A
@QuarkusTestthat calls an endpoint backed by PostgreSQL should pass without any manual database setup.
Verifying production-like behavior
Dev Services is disabled by default outside dev and test profiles. To confirm your production configuration is complete, build and run a native executable:
./mvnw package -Pnative
When you run the resulting binary, Quarkus should not attempt to start a container. If no real database URL is configured, the application fails fast during startup. This failure is expected and confirms that Dev Services did not leak into the production artifact.
Limitations and recovery options
Dev Services is intentionally scoped to local development and automated tests. It is not a production provisioning tool.
| Scenario | Recommended approach |
|---|---|
Custom PostgreSQL extensions (for example, PostGIS or specific postgresql.conf settings) | Dev Services uses a standard image. Build a custom container image and reference it with quarkus.datasource.devservices.image-name, or use Docker Compose for complex setups. |
| Persistent local data across restarts | Dev Services containers are ephemeral. Use an external PostgreSQL instance or configure Testcontainers volume mappings manually. |
| CI environments without Docker | Dev Services cannot start. Configure a real PostgreSQL service in the CI pipeline and set quarkus.datasource.jdbc.url explicitly. |
| Need to disable Dev Services temporarily | Set quarkus.datasource.devservices.enabled=false in application.properties and provide an explicit JDBC URL. |
Practical verification checklist
- Start dev mode and confirm the logs report a Dev Services PostgreSQL container on a dynamic port.
- Run your integration tests and confirm they pass without an external database.
- Build a native image and run it without Docker to confirm the application requires a real datasource configuration.
If dev mode fails to start the container, check that the Docker daemon is running and that your user can execute docker ps. If the application cannot connect despite a started container, inspect the full startup log for readiness timeout messages and verify that no firewall blocks the dynamically assigned port on localhost.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.