spring.datasource.url

The JDBC URL of the application's database; Boot builds a pooled DataSource from it and infers the driver from the URL.

Signature
spring.datasource.url=jdbc:postgresql://localhost:5432/orders
  • Added in Spring Boot Spring Boot 4.1 (verified present)

Parameters

ParameterTypeDescription
$valueoptionalStringA JDBC URL such as jdbc:postgresql://host:5432/db or jdbc:h2:mem:test. When it is unset and an embedded database is on the classpath, Boot creates an in-memory database instead.
$spring.datasource.usernameoptionalStringLogin user for the database.
$spring.datasource.passwordoptionalStringLogin password. Supply it from the environment or a secret store, never from a committed file.
$spring.datasource.driver-class-nameoptionalStringFully qualified JDBC driver class. Normally inferred from the URL.

Return value

n/aThe JDBC URL used to create the auto-configured DataSource (a HikariCP pool by default). It names the driver, host, port, database and any driver options.

Errors

Without a URL and without an embedded database, startup fails with 'Failed to configure a DataSource: url attribute is not specified'.

spring.datasource.url tells Boot where the database is. With the JDBC or JPA starter on the classpath and this property set, Boot creates a HikariCP connection pool, works out the driver class from the URL prefix, and hands the pool to JdbcClient, JdbcTemplate, JPA and Flyway.

spring.datasource.url=jdbc:postgresql://localhost:5432/orders
spring.datasource.username=orders_app
spring.datasource.password=${DB_PASSWORD}

What the URL contains

A JDBC URL is driver-specific: jdbc:postgresql://host:port/database for PostgreSQL, jdbc:h2:mem:name for an in-memory H2 database. Driver options go on the end as query parameters, for example ?ApplicationName=orders so the database can tell your connections apart from everyone else's in its activity view.

When the URL is missing

If no URL is set and H2 (or another embedded database) is on the classpath, Boot quietly creates an in-memory database with a generated name. That is convenient for a first run and a trap later: the application starts, data disappears on restart, and nobody notices until a demo. If no embedded database is available either, startup stops with Failed to configure a DataSource: 'url' attribute is not specified. In practice that message usually means the profile that sets the URL was not active.

Where the value should come from

The URL differs per environment and the password is a secret, so neither belongs in a committed application.properties for production. Use SPRING_DATASOURCE_URL, SPRING_DATASOURCE_USERNAME and SPRING_DATASOURCE_PASSWORD environment variables, a mounted config tree, or a secret manager imported with spring.config.import. In development, the Docker Compose support and @ServiceConnection in tests supply connection details from the running container, so you often do not set the URL at all.

Pool settings live next to it

The URL only says where; how many connections and how long to wait are pool settings under spring.datasource.hikari.*. The default maximum of ten connections per instance multiplied by your replica count must stay under the database's connection limit, which is a common cause of outages after a scale-up.

Defining your own DataSource bean switches this auto-configuration off, and the spring.datasource.* properties stop applying unless you bind them yourself. The exception is a bean declared with @Bean(defaultCandidate = false): Boot ignores it when deciding whether to back off, so an extra pool can sit next to the auto-configured one.

Example

Example · properties
# application-prod.properties: values come from the environment at runtime.
spring.datasource.url=${DB_URL:jdbc:postgresql://localhost:5432/orders?ApplicationName=orders-api}
spring.datasource.username=${DB_USER:orders_app}
spring.datasource.password=${DB_PASSWORD}

# The pool that Boot builds around the URL.
spring.datasource.hikari.maximum-pool-size=10
spring.datasource.hikari.connection-timeout=5s

When to use it

  • Pointing the same jar at a local, staging and production PostgreSQL through environment variables
  • Running repository tests against a throwaway PostgreSQL container instead of a shared database
  • Reading reports from a replica database alongside the main read-write database

Frequently asked questions

Why does Spring Boot say 'Failed to configure a DataSource: url attribute is not specified'?

A JDBC or JPA starter is on the classpath, no spring.datasource.url is set, and there is no embedded database to fall back to. Usually the profile that defines the URL is not active, or the environment variable was not passed to the process.

Do I need to set spring.datasource.driver-class-name?

Rarely. Boot infers the driver from the URL prefix for the common databases. Set it only for an unusual driver or when you want a specific class.

How do I set the database URL with an environment variable?

Export SPRING_DATASOURCE_URL (and SPRING_DATASOURCE_USERNAME, SPRING_DATASOURCE_PASSWORD). Relaxed binding maps them onto the spring.datasource properties and they override values in application.properties.

More examples

Different databases per profile

The default document points at a local PostgreSQL. The demo profile switches to an in-memory H2 database that lives as long as the JVM. Keep the production URL out of this file entirely and supply it from the environment.

Example · yaml
spring:
  datasource:
    url: jdbc:postgresql://localhost:5432/orders
    username: orders_app
    password: ${DB_PASSWORD:localdev}
---
spring:
  config:
    activate:
      on-profile: demo
  datasource:
    url: jdbc:h2:mem:orders;DB_CLOSE_DELAY=-1
    username: sa
    password: ""

A test that gets its URL from a container

@ServiceConnection supplies the container's JDBC URL, user and password, and they take precedence over spring.datasource.url. @AutoConfigureTestDatabase defaults to Replace.NON_TEST, which leaves a DataSource that comes from a test service connection in place, so the test runs against real PostgreSQL. Add replace = Replace.NONE only when the URL comes from ordinary configuration instead.

Example · java
import static org.assertj.core.api.Assertions.assertThat;

import java.sql.Connection;
import javax.sql.DataSource;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.jdbc.test.autoconfigure.JdbcTest;
import org.springframework.boot.testcontainers.service.connection.ServiceConnection;
import org.testcontainers.junit.jupiter.Container;
import org.testcontainers.junit.jupiter.Testcontainers;
import org.testcontainers.postgresql.PostgreSQLContainer;

@JdbcTest
@Testcontainers
class DataSourceConnectionTest {

    @Container
    @ServiceConnection
    static PostgreSQLContainer postgres = new PostgreSQLContainer("postgres:18-alpine");

    @Autowired
    DataSource dataSource;

    @Test
    void connectsToTheContainerNotTheConfiguredUrl() throws Exception {
        try (Connection connection = dataSource.getConnection()) {
            assertThat(connection.getMetaData().getURL()).startsWith("jdbc:postgresql://");
            assertThat(connection.getMetaData().getDatabaseProductName()).isEqualTo("PostgreSQL");
        }
    }
}

A second database bound from your own prefix

DataSourceProperties understands url, username and password, so the reporting database uses the same keys under app.reporting.datasource, and its pool settings go under app.reporting.datasource.hikari. Because both beans are declared with defaultCandidate = false, Boot does not back off: the main pool is still built from spring.datasource.* and JPA and Flyway keep using it. Inject the reporting pool with @Qualifier("reporting").

Example · java
import com.zaxxer.hikari.HikariDataSource;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.jdbc.autoconfigure.DataSourceProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class ReportingDataSourceConfig {

    // defaultCandidate = false: Boot still auto-configures the main DataSource
    // from spring.datasource.*, and nothing receives these beans by type alone.
    @Bean(defaultCandidate = false)
    @Qualifier("reporting")
    @ConfigurationProperties("app.reporting.datasource")
    DataSourceProperties reportingDataSourceProperties() {
        return new DataSourceProperties();
    }

    @Bean(defaultCandidate = false)
    @Qualifier("reporting")
    @ConfigurationProperties("app.reporting.datasource.hikari")
    HikariDataSource reportingDataSource(@Qualifier("reporting") DataSourceProperties properties) {
        return properties.initializeDataSourceBuilder().type(HikariDataSource.class).build();
    }
}

Discussion

  • Be the first to comment on this lesson.