Using Quarkus Dev Services to Run Databases Automatically in Development
Quarkus Dev Services automatically start and manage containers like PostgreSQL during dev and test, removing manual setup while preserving state across live reloads.
17 Aug 2025, 17:34 UTC

Problem: repetitive container setup slows inner‑loop development
When you write integration tests that need a database, you often spend time manually starting a Docker container, configuring connection properties, and tearing it down after each run. This adds friction and can cause tests to fail if the container isn’t ready.
Thesis: Quarkus Dev Services eliminate manual container management by launching and managing testcontainers for you, while preserving state across live reloads.
How Dev Services work
Dev Services are a built‑in feature that watches for extensions that declare a need for a service (e.g., quarkus-jdbc-postgresql). When the application starts in dev or test mode, Quarkus checks whether a matching container is already running; if not, it pulls the appropriate image and starts a container with sensible defaults (PostgreSQL on port 5432, Kafka on 9092, etc.). The container stays alive across code changes thanks to Quarkus’ live reload, so you don’t lose database state while iterating.
Worked example: adding a PostgreSQL Dev Service
Create a Quarkus project (run where you have Maven and Docker access):
mvn io.quarkus:quarkus-maven-plugin:create \ -DprojectGroupId=org.example \ -DprojectArtifactId=quarkus-devservice-demo \ -DclassName="org.example.GreetingResource" \ -Dpath="/hello"Add the PostgreSQL JDBC extension:
cd quarkus-devservice-demo ./mvnw quarkus:add-extension -Dextensions="quarkus-jdbc-postgresql"Write a simple test that injects the datasource:
package org.example; import io.quarkus.test.junit.QuarkusTest; import jakarta.inject.Inject; import jakarta.sql.DataSource; import org.junit.jupiter.api.Test; import static org.junit.jupiter.api.Assertions.assertNotNull; @QuarkusTest class DatabaseTest { @Inject DataSource ds; @Test void datasourceIsAvailable() { assertNotNull(ds); } }Run the test suite:
./mvnw testDuring execution you should see Docker pull the
postgresimage (if not cached) and start a container on port 5432. The test passes because Dev Services automatically configuredquarkus.datasource.jdbc.urlto point at that container.Verify the container is running:
docker ps --filter "ancestor=postgres" --format "{{.Names}}"You will see a name like
devservices-postgres.
Overriding defaults
You can disable Dev Services for a specific service or change the image via application.properties:
# Disable PostgreSQL Dev Service
quarkus.datasource.devservices.enabled=false
# Use a custom PostgreSQL version
quarkus.datasource.devservices.image-name=postgres:15-alpine
These overrides are useful in CI pipelines where you may want to rely on externally provisioned services or avoid pulling images.
Trade‑offs and limitations
Docker dependency: Dev Services require a reachable Docker daemon. Running on CI agents without Docker (e.g., some hosted macOS runners) will cause tests to fail unless you explicitly set
quarkus.* .devservices.enabled=false.Version drift risk: The default image may differ from the version used in production. If you rely on the default, periodically verify that the Dev Service image matches your production database version to avoid surprising migration failures.
Native executables: By default, Dev Services are disabled when building a native image (
-Pnative) to avoid pulling heavy containers at runtime. To use them in native‑mode tests, launch the test suite with-Dquarkus.devservices.enabled=true.
Actionable closing
Start by enabling Dev Services for the services you need in development; they give you instant, disposable containers with zero manual setup. Keep an eye on Docker availability and consider pinning explicit images in application.properties when your production environment uses a specific version. When you move to CI, disable Dev Services for services that are already provisioned, or rely on the -Dquarkus.devservices.enabled=true flag for native‑mode testing. This approach lets you focus on writing code instead of managing containers.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.