Spring Boot
Application Properties
Environment Variables
Java
Programming

Using env variable in Spring Boot's application.properties

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

Spring Boot makes it easy to read configuration from environment variables, either directly through its property binding system or indirectly through placeholders in application.properties. This is one of the cleanest ways to keep secrets and environment-specific settings out of source code while still giving the application sensible defaults.

The Basic Placeholder Syntax

Inside application.properties, the most common pattern is:

properties
app.name=${APP_NAME:demo-service}
app.region=${APP_REGION:local}

This means:

  • read APP_NAME if it exists
  • otherwise use demo-service

The part after the colon is the default value. If you omit it, the property becomes required unless some other source provides a value.

This is especially useful for configuration that changes by environment, such as:

  • database URLs
  • API keys
  • host names
  • feature flags

A Real Spring Boot Example

A common case is database configuration:

properties
spring.datasource.url=${DB_URL:jdbc:postgresql://localhost:5432/app}
spring.datasource.username=${DB_USER:appuser}
spring.datasource.password=${DB_PASSWORD:changeme}

Then you can export variables before starting the application:

bash
1export DB_URL=jdbc:postgresql://db.prod.internal:5432/app
2export DB_USER=prod_user
3export DB_PASSWORD=super-secret
4./mvnw spring-boot:run

The application will use the environment values at runtime. If those variables are missing in local development, the defaults in application.properties still let the app start.

Direct Environment Binding Without Placeholders

Spring Boot can also bind environment variables directly to configuration properties without any placeholder in the file.

For example, this environment variable:

bash
export SPRING_DATASOURCE_URL=jdbc:postgresql://localhost:5432/app

maps directly to the Spring property spring.datasource.url.

That works because Spring Boot uses relaxed binding rules. Dots become underscores, and names are typically uppercase in the shell environment.

So there are two valid styles:

  • direct binding through variables such as SPRING_DATASOURCE_URL
  • placeholders inside application.properties such as ${DB_URL:...}

The direct style is great when the environment variable name already matches the Spring property. Placeholder style is useful when you want a custom variable name or an explicit default in the file.

Binding Into a Configuration Class

The value eventually flows into your beans the same way as any other property. For example:

java
1import org.springframework.boot.context.properties.ConfigurationProperties;
2
3@ConfigurationProperties(prefix = "mail")
4public class MailProperties {
5
6    private String host;
7    private int port;
8
9    public String getHost() {
10        return host;
11    }
12
13    public void setHost(String host) {
14        this.host = host;
15    }
16
17    public int getPort() {
18        return port;
19    }
20
21    public void setPort(int port) {
22        this.port = port;
23    }
24}

With properties like:

properties
mail.host=${MAIL_HOST:localhost}
mail.port=${MAIL_PORT:1025}

That lets you keep strongly typed configuration in Java while still sourcing the values from the environment.

Where Environment Variables Are Most Useful

Environment variables are usually best for deployment-specific values rather than stable application defaults.

Good candidates include:

  • credentials
  • service endpoints
  • region names
  • queue names
  • timeouts that vary by environment

Less ideal candidates are large structured documents or sprawling configuration trees that are hard to manage as flat variables. For those, profile-specific property files, config servers, or secret managers may be cleaner.

Be Careful With Secrets

Environment variables are better than hardcoding passwords into source control, but they are not magically private. They can still appear in process listings, container definitions, CI logs, or platform dashboards depending on the environment.

So the mature approach is:

  • use environment variables for ordinary deploy-time configuration
  • use secret stores or platform secret injection for sensitive values when available
  • avoid printing those values in startup logs

Spring Boot will happily bind the values either way. Security depends on how you supply them.

Common Pitfalls

The most common pitfall is mixing up the environment variable name with the property name. DB_URL and SPRING_DATASOURCE_URL are not interchangeable unless your placeholder or binding setup says they are.

Another mistake is forgetting the default value syntax and expecting ${NAME} to behave like ${NAME:default}. Without the default, startup may fail if the variable is missing.

A third issue is putting secrets in application.properties defaults and forgetting that the file may be committed to source control.

Finally, teams sometimes overuse environment variables for every setting. Use them where externalization helps, not just because the feature exists.

Summary

  • Spring Boot can read environment variables directly or through placeholders in application.properties.
  • The placeholder form ${NAME:default} is the usual way to provide a fallback value.
  • Direct binding also works for names such as SPRING_DATASOURCE_URL.
  • Environment variables are ideal for deploy-specific configuration and safer than hardcoding values.
  • Sensitive secrets still need careful handling even when they come from the environment.

Course illustration
Course illustration

All Rights Reserved.