Implementing Local Data Persistence with Quarkus Dev Services for PostgreSQL
Learn how to use Quarkus Dev Services to automatically provision PostgreSQL containers for local development, eliminating manual database setup and configuration friction.
12 Jul 2026, 02:46 UTC

The Problem: Database Configuration Friction
Setting up a local database for development often creates a "bootstrap bottleneck." Developers must manually install PostgreSQL, manage versions, create databases, and synchronize credentials across a team. This manual process leads to "it works on my machine" errors when local environments diverge from CI pipelines or other teammates' setups.
The takeaway: Quarkus Dev Services removes this friction by automatically provisioning a PostgreSQL container via Testcontainers during development and testing, requiring zero manual configuration to get a functional database.
The Smallest Suitable Design
To implement this, the application requires only the presence of the PostgreSQL extension and a running container engine (such as Docker or Podman). The system follows a "convention over configuration" pattern: if the application detects a PostgreSQL extension but finds no explicit datasource URL in the configuration, it triggers the Dev Services lifecycle.
Required Extensions
Depending on your persistence layer, add one of the following to your pom.xml:
- Hibernate ORM:
quarkus-hibernate-orm-panache(for JDBC-based blocking access) - Reactive PostgreSQL:
quarkus-reactive-pg-client(for non-blocking access)
Automatic Provisioning Logic
When you run ./mvnw quarkus:dev, the following sequence occurs:
- Quarkus checks for the
quarkus.datasource.jdbc.urlproperty. - If the property is missing, Quarkus invokes Testcontainers to pull the official PostgreSQL image.
- A container is started on a random available port to avoid conflicts.
- Quarkus dynamically injects the generated URL, username, and password into the application context.
Trust and Data Boundaries
Dev Services operate within a specific trust boundary: the local development environment. It is critical to understand where the boundaries lie to avoid security leaks.
Image Integrity
The application process relies on the local container runtime to pull images from a public registry. In high-security environments, this introduces a dependency on the registry's integrity. To mitigate this, organizations can configure a private registry mirror.
Data Volatility
By default, Dev Services containers are ephemeral. Data is lost when the Quarkus dev session ends. If your development requires persistent state across restarts, you must move beyond Dev Services and configure a standalone database or a named Docker volume.
Operational Checks and Verification
To verify that Dev Services is functioning correctly and not relying on a hidden local installation, perform these checks.
Verification Steps
- Start the App: Run
./mvnw quarkus:dev. - Check Logs: Look for a log entry similar to
Dev Services for PostgreSQL started. - Inspect Properties: Check the console output for the dynamically assigned JDBC URL (e.g.,
jdbc:postgresql://localhost:32768/quarkus).
Diagnostic Comparison
Use the following table to determine if Dev Services is active or if the app is using a manual configuration:
| Scenario | Configuration State | Behavior | Result |
|---|---|---|---|
| Dev Services Active | No datasource.jdbc.url defined |
Container starts automatically | Dynamic port assigned |
| Manual Config | datasource.jdbc.url defined |
Dev Services is bypassed | Connects to specified host/port |
| Disabled | quarkus.devservices.enabled=false |
Container does not start | Startup failure (if no URL provided) |
Failure Modes
Several conditions can cause Dev Services to fail, preventing the application from starting:
- Container Runtime Unavailability: If Docker or Podman is not running, Quarkus will log a warning and fail to start the database.
- Network Restrictions: In air-gapped environments, the image pull will fail. This requires pre-loading the image into the local cache.
- Port Exhaustion/Conflicts: While rare due to random port assignment, firewall rules blocking high-range ports can prevent the application from reaching the container.
Design Pivot Points
Dev Services is a productivity tool, not a deployment strategy. You must change this design under the following conditions:
- Production Deployment: Dev Services are explicitly disabled in production. You must provide a real connection string via environment variables (e.g.,
QUARKUS_DATASOURCE_JDBC_URL). - Fixed Schema Requirements: If your tests require a specific, pre-populated database state that cannot be handled by Hibernate's
drop-and-create, you should switch to a managed test database or a custom Testcontainers setup. - Offline CI: If your CI pipeline cannot access the internet to pull images, you must configure a local image registry or use a pre-installed database service.
Rollback/Disabling
To stop using Dev Services and revert to manual configuration, add the following to your src/main/resources/application.properties:
quarkus.devservices.enabled=false
quarkus.datasource.jdbc.url=jdbc:postgresql://your-host:5432/your-db
quarkus.datasource.username=user
quarkus.datasource.password=pass0 replies
A thoughtful contribution can make all the difference. Be the first to share one.