Real World Example

Twelve-Factor Config

Companies like Netflix, Swiggy and Razorpay follow the 12-factor rule "store config in the environment": the same jar (or Docker image) is promoted from test to staging to production, and only the environment changes. No rebuild per environment, no secrets in Git.

ShopEase: Running the Same Jar Everywhere

Example

Production server: secrets come from the environment, the profile from SPRING_PROFILES_ACTIVE.

export SPRING_PROFILES_ACTIVE=prod
export DB_URL=jdbc:mysql://10.0.0.5:3306/shopease
export DB_USER=shopease
export DB_PASSWORD='s3cr3t-from-vault'
export SHOPEASE_PAYMENT_KEYID=rzp_live_AbC123
export SHOPEASE_PAYMENT_KEYSECRET='from-secret-manager'
java -jar shopease-1.4.0.jar

Example output

INFO  c.s.ShopEaseApplication : The following 1 profile is active: "prod"
INFO  com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Start completed.
INFO  o.s.b.w.e.tomcat.TomcatWebServer : Tomcat started on port 8080 (http) with context path '/'
INFO  c.s.ShopEaseApplication : Started ShopEaseApplication in 4.812 seconds
// A tiny endpoint the ops team uses to check which config is live (no secrets!)
@RestController
class InfoController {
    private final PaymentProperties payment;
    private final Environment env;

    InfoController(PaymentProperties payment, Environment env) { this.payment = payment; this.env = env; }

    @GetMapping("/api/info")
    Map<String, Object> info() {
        return Map.of("profiles", env.getActiveProfiles(),
                      "paymentBaseUrl", payment.baseUrl(),
                      "paymentTimeout", payment.timeout().toString());
    }
}

Example

curl localhost:8080/api/info

Example output

{"profiles":["prod"],"paymentBaseUrl":"https://api.razorpay.com","paymentTimeout":"PT5S"}

Tip: In the advanced level, Spring Boot Actuator's /actuator/env and /actuator/configprops show this too (with secrets masked).