Real World Example

Configuration at Scale

Apps like Zomato or a bank's mobile banking backend run the same jar in development, staging and production. Only the configuration changes. Secrets (database passwords, payment keys) are never committed to Git; they come from environment variables or a secrets manager.

same shopease.jar
         /        |         \
   dev laptop   staging     production
   profile=dev  profile=    profile=prod
   local MySQL  staging     DB_PASSWORD from env / vault
                RAZORPAY_KEY=test   RAZORPAY_KEY=live

ShopEase Configuration

application.yml

application.yml

spring:
  application:
    name: shopease
server:
  port: ${PORT:8080}                 # cloud platforms often set PORT
shopease:
  currency: INR
  free-delivery-above: 499
  delivery-charge: 40
  razorpay:
    key-id: ${RAZORPAY_KEY_ID:rzp_test_dummy}    # real key only from the environment
@RestController
public class DeliveryController {
    private final DeliveryChargeService service;

    public DeliveryController(DeliveryChargeService service) {
        this.service = service;
    }

    @GetMapping("/api/delivery-charge")
    public Map<String, Object> charge(@RequestParam int cartTotal) {
        return Map.of("cartTotal", cartTotal, "deliveryCharge", service.chargeFor(cartTotal));
    }
}

Example

curl "http://localhost:8080/api/delivery-charge?cartTotal=350"
curl "http://localhost:8080/api/delivery-charge?cartTotal=1499"

Example output

{"cartTotal":350,"deliveryCharge":"40 INR"}
{"cartTotal":1499,"deliveryCharge":"0 INR"}

Checklist

  • Shared defaults in application.yml, differences in application-{profile}.yml.
  • Secrets only through ${ENV_VAR} placeholders; add a harmless default for local runs.
  • Never hard-code ports, URLs or keys in Java code; read them from configuration.