Advanced Reading time: ~10 min

Spring Cloud

config server, service discovery, load balancing

Spring Cloud

Spring Cloud provides the operational patterns that turn a set of Spring Boot services into a centrally configured, discoverable, and dynamically connected system.

1. Definíció / Definition

Mi ez? / What is it?

Spring Cloud is the Spring ecosystem layer focused on distributed-system concerns. It is not a single framework feature but a collection of integration modules for centralized configuration, service discovery, client-side load balancing, API gateways, messaging-based refresh, and resilience patterns. In practice, it standardizes how many independent Spring Boot services behave as one platform.

Miért létezik? / Why does it exist?

Microservices quickly accumulate infrastructure problems that business teams should not solve from scratch in every codebase: where configuration lives, how services locate each other, how traffic is balanced across instances, how secrets are managed, and how runtime configuration changes propagate safely. Spring Cloud exists to provide conventions, integration points, and production-oriented defaults around those recurring concerns.

Hol helyezkedik el? / Where does it fit?

It sits above Spring Boot and below business logic. A service can still be a normal Spring Boot application, but Spring Cloud shapes how that application starts, loads configuration, registers itself, resolves peer services, and reacts to operational changes without redeployment.

2. Alapfogalmak / Core Concepts

2.1 Spring Cloud Config Server

Spring Cloud Config Server externalizes configuration into a dedicated service. Instead of embedding all environment-specific properties inside each deployable artifact, applications fetch configuration from a remote source, commonly Git or Vault.

Typical configuration flow:

  1. A Git repository or Vault stores the source configuration.
  2. Config Server exposes that configuration over HTTP.
  3. Config Clients load the remote properties during startup or refresh.
Component Responsibility Production value
Config Server Exposes configuration over HTTP Central control point
Git backend Versioned property source Auditable change history
Vault backend Secret-focused configuration source Better secret hygiene
Config Client Loads remote properties Cleaner deploy pipeline

Git-backed configuration is useful because configuration changes become reviewable, revertible, and traceable like code. Vault-backed configuration matters when the concern is secret lifecycle, rotation, and access control rather than simple property storage.

2.2 Bootstrap context vs application context

Historically, Spring Cloud used a bootstrap context that was created before the main application context. Its purpose was to load remote configuration early enough for core startup decisions. In newer Spring Boot generations, the Config Data API changed the mechanics, but the conceptual distinction still matters: some configuration must be available before normal bean initialization begins.

Startup precedence summary:

  • Bootstrap context — loads remote configuration early so critical startup properties exist in time.
  • Application context — creates the real Spring beans and wiring using the resolved properties.

This explains many startup issues in legacy projects. If engineers do not understand property source precedence and early loading, configuration bugs become mysterious and expensive to diagnose.

2.3 Service discovery with Eureka

Eureka Server acts as a service registry. Service instances register themselves, renew their lease with heartbeats, and become discoverable by name. Other services query Eureka rather than relying on hard-coded hostnames.

Typical discovery cycle:

  1. inventory-service and order-service register themselves in Eureka Server.
  2. Each service keeps its lease alive with periodic heartbeats.
  3. A caller resolves inventory-service by name through Eureka instead of using fixed hosts.

Important terms:

  • registration: an instance announces its location and metadata;
  • heartbeat/renewal: periodic signal that the instance is still alive;
  • lease expiration: an instance is removed when renewals stop;
  • self-preservation: a safety mode that avoids mass eviction during network instability.

2.4 Client-side load balancing

Ribbon was the historical Netflix solution; Spring Cloud LoadBalancer is the modern replacement. The idea remains the same: the client receives the available instances and chooses one locally.

Option Status Main idea
Ribbon Legacy Older Netflix stack integration
Spring Cloud LoadBalancer Current Spring-native instance selection
@LoadBalanced RestTemplate Convenience integration Resolve service IDs to live instances

This is different from server-side load balancing, where a reverse proxy or ingress makes the selection. In client-side load balancing, the application itself participates in discovery and routing decisions.

2.5 `@EnableDiscoveryClient`, `@LoadBalanced`, `@RefreshScope`

  • @EnableDiscoveryClient marks an application as discovery-aware. Auto-configuration often makes it optional, but the concept remains important.
  • @LoadBalanced RestTemplate enables service-name-based HTTP calls such as http://inventory-service/....
  • @RefreshScope rebuilds scoped beans after a refresh event so new configuration values can take effect without a full restart.

2.6 Spring Cloud Bus

Config Server centralizes configuration, but propagation is a separate concern. Spring Cloud Bus uses a message broker such as RabbitMQ or Kafka to broadcast refresh events across many services.

Refresh propagation flow:

  1. A configuration change is committed or published.
  2. Spring Cloud Bus emits a refresh event through the broker.
  3. Multiple services reload the updated configuration.

Without a bus, teams often refresh instances one by one. With a bus, configuration refresh becomes coordinated and scalable.

3. Gyakorlati használat / Practical Usage

A realistic platform might contain config-repo, config-server, eureka-server, and multiple business services such as order-service, payment-service, and inventory-service. At startup, each service loads environment-specific configuration, then registers with Eureka, then begins resolving peer services by logical name instead of physical address.

This model is especially useful in environments where instances are elastic or ephemeral. Virtual machines, auto-scaling groups, and mixed cloud/on-prem deployments all benefit from discovery and centralized configuration. Even in Kubernetes-heavy organizations, Spring Cloud can still be relevant when teams want application-level integration patterns rather than only platform primitives.

A common production scenario is controlled runtime configuration change. Suppose fraud thresholds, feature toggles, rate limits, or downstream timeout values live in the configuration repository. An approved change is committed, Config Server exposes it, and Spring Cloud Bus propagates the refresh event. Services using @RefreshScope can adopt the new values without a full rebuild or redeploy.

Another practical scenario is multi-region or multi-profile deployment. The same application artifact can run with dev, staging, prod, or prod-eu configuration sets. This reduces artifact drift and improves auditability because environment variation is explicit and centralized.

4. Kód példák / Code Examples

4.1 Config Server setup

@SpringBootApplication
@EnableConfigServer
public class ConfigServerApplication {

    public static void main(String[] args) {
        SpringApplication.run(ConfigServerApplication.class, args);
    }
}
server:
  port: 8888
spring:
  cloud:
    config:
      server:
        git:
          uri: https://github.com/acme/platform-config
          default-label: main

4.2 Config Client with `@RefreshScope`

@RestController
@RefreshScope
class FeatureFlagsController {

    @Value("${features.checkout-fast-path:false}")
    private boolean checkoutFastPath;

    @GetMapping("/internal/features")
    public Map<String, Boolean> features() {
        return Map.of("checkoutFastPath", checkoutFastPath);
    }
}
spring:
  application:
    name: checkout-service
  config:
    import: optional:configserver:http://localhost:8888
management:
  endpoints:
    web:
      exposure:
        include: health,info,refresh,busrefresh

4.3 Eureka server and discovery client

@SpringBootApplication
@EnableEurekaServer
public class DiscoveryServerApplication {

    public static void main(String[] args) {
        SpringApplication.run(DiscoveryServerApplication.class, args);
    }
}
@SpringBootApplication
@EnableDiscoveryClient
public class PaymentApplication {

    public static void main(String[] args) {
        SpringApplication.run(PaymentApplication.class, args);
    }
}

4.4 Client-side load balancing with `RestTemplate`

@Configuration
class ClientConfig {

    @Bean
    @LoadBalanced
    RestTemplate restTemplate(RestTemplateBuilder builder) {
        return builder.build();
    }
}

@Service
class InventoryClient {
    private final RestTemplate restTemplate;

    InventoryClient(RestTemplate restTemplate) {
        this.restTemplate = restTemplate;
    }

    public InventoryDto getInventory(String sku) {
        return restTemplate.getForObject(
                "http://inventory-service/api/inventory/{sku}",
                InventoryDto.class,
                sku
        );
    }
}

record InventoryDto(String sku, int available) {}

4.5 Publishing a refresh event over the bus

@RestController
class ConfigOperationsController {

    private final ApplicationEventPublisher publisher;

    ConfigOperationsController(ApplicationEventPublisher publisher) {
        this.publisher = publisher;
    }

    @PostMapping("/internal/config/refresh")
    ResponseEntity<Void> refreshCluster() {
        publisher.publishEvent(new RefreshRemoteApplicationEvent(this, null, null));
        return ResponseEntity.accepted().build();
    }
}

5. Trade-offok / Trade-offs

Benefits

  • centralizes environment configuration and supports reviewable change management;
  • removes many hard-coded network dependencies through discovery;
  • enables dynamic instance selection for service-to-service calls;
  • makes some configuration changes operationally cheaper than full redeployment.

Costs

  • introduces additional infrastructure services and failure modes;
  • increases startup complexity and property-loading nuance;
  • may duplicate platform capabilities already provided elsewhere;
  • creates hidden coupling if teams overuse runtime refresh.

Use it when you operate multiple Spring services, need shared configuration governance, and benefit from service discovery or cluster-wide refresh workflows.

Avoid it when a simple monolith or a platform-native solution already solves the problem with less complexity.

6. Gyakori hibák / Common Mistakes

6.1 Storing secrets in plain Git-backed config

Git-backed config is convenient, but many teams stretch it too far. Database passwords, API tokens, and private keys should not live as plain properties in a normal repository. Use Vault or another secret-management strategy.

6.2 Treating `@RefreshScope` as magic

@RefreshScope recreates beans, but it does not automatically fix every mutable state problem. Constructor-captured values, caches, thread pools, and long-lived connections may still need explicit lifecycle design.

6.3 Over-tuning Eureka lease settings

Very short heartbeat or eviction timing may look attractive in testing, but unstable networks can create instance flapping in production. Rapid registration and eviction cycles amplify incident noise instead of improving recovery.

6.4 Using service discovery for everything

Not every endpoint belongs in a registry. External SaaS APIs, databases, and stable infrastructure services often do not benefit from discovery semantics. Use discovery where endpoints are dynamic and service-oriented.

6.5 Mixing bootstrap-era examples with modern config loading

Teams maintaining both legacy and newer projects often confuse bootstrap configuration with spring.config.import-based loading. The resulting mistakes typically show up as missing properties or unexpected precedence behavior.

7. Senior szintű meglátások / Senior-level Insights

At senior level, Spring Cloud should be evaluated as a platform choice, not a default dependency. The real question is which operational problems it solves better than your runtime platform. In Kubernetes, for example, some discovery and configuration concerns already exist natively, but Spring Cloud may still provide consistent application-level abstractions across heterogeneous environments.

Treat configuration as a release artifact. A bad configuration change can be just as damaging as a bad binary. That means code review, rollout discipline, observability, rollback procedures, and ownership models should apply to configuration repositories as seriously as they apply to source code.

Eureka is eventually consistent, not transactional truth. Clients must still use sane timeouts, retries, and resilience patterns because discovery can lag behind reality for short periods. A registry reduces hard-coding; it does not remove distributed-systems uncertainty.

Finally, be conservative with runtime refresh. Cluster-wide refresh looks operationally elegant, but it also increases blast radius. Not every property deserves hot reloading. For high-risk settings, a deliberate rollout may be safer than dynamic mutation across the fleet.

8. Szószedet / Glossary

  • Config Server: a centralized service that exposes externalized configuration.
  • Config Client: an application that loads configuration from Config Server.
  • Eureka: a service registry used for discovery and registration.
  • Heartbeat: a periodic renewal proving an instance is still alive.
  • Client-side load balancing: local instance selection performed by the caller.
  • @RefreshScope: a scope that rebuilds beans after refresh events.
  • Bootstrap context: early context used to load critical configuration before the main application context.
  • Spring Cloud Bus: a broker-backed mechanism for distributing refresh events and other signals.

9. Gyorsreferencia / Cheatsheet

Topic Purpose Key annotation / element Frequent pitfall
Config Server Centralized configuration @EnableConfigServer Plain-text secrets
Config Client Remote property loading spring.config.import Property precedence confusion
Eureka Discovery and registration @EnableDiscoveryClient Unstable lease tuning
LoadBalancer Instance selection @LoadBalanced Mixing service IDs with fixed URLs
Refresh Runtime config reload @RefreshScope Stateful beans behaving badly
Bus Cluster-wide refresh propagation busrefresh endpoint Excessive blast radius

🎮 Games

8 questions