skip to content

Spring Cloud Bus

Spring Cloud Bus links instances over Kafka or RabbitMQ so one busrefresh call reconfigures the whole cluster. It answers the obvious follow-up to per-instance refresh: how do you avoid calling fifty endpoints.

part ofSpring Frameworkoverview, primer and where to startread it →
on this pageshow

questions

5

What is Spring Cloud Bus and what problem does it solve?

level: juniorimportance: must knowfreq 55%

answer

  1. Broker links all instances (Kafka/Rabbit)
  2. One busrefresh -> whole cluster
  3. vs per-instance /actuator/refresh
  4. Built on Stream, topic springCloudBus
  5. starter-bus-amqp / starter-bus-kafka

basics

~20 s

Spring Cloud Bus links all instances of your microservices through a shared message broker (Kafka or RabbitMQ). You can then broadcast one message — like 'refresh your config' — to the whole cluster at once instead of calling each instance.

solid answer

~40 s

Spring Cloud Bus connects application instances over a lightweight message broker (RabbitMQ or Kafka) so they can broadcast events to each other. Its most common use is distributed configuration refresh: after you change values in a config repo, you POST once to /actuator/busrefresh on any single instance, and the Bus propagates a RefreshRemoteApplicationEvent across the broker to every instance, each of which re-reads its config and rebinds @RefreshScope / @ConfigurationProperties beans. Without the Bus you'd have to call /actuator/refresh on each instance individually, which doesn't scale. Under the hood the Bus is built on Spring Cloud Stream, using a shared topic (default 'springCloudBus') as the broadcast channel. You add it with spring-cloud-starter-bus-amqp or spring-cloud-starter-bus-kafka.

code

yaml · 18 lines
yaml
# build.gradle: implementation 'org.springframework.cloud:spring-cloud-starter-bus-amqp'

# application.yml
spring:
  rabbitmq:
    host: rabbit.internal
    port: 5672
    username: app
    password: ${RABBIT_PASSWORD}

management:
  endpoints:
    web:
      exposure:
        include: busrefresh   # must expose the Actuator endpoint

# Trigger a cluster-wide refresh with ONE call to ANY instance:
#   curl -X POST http://any-instance:8080/actuator/busrefresh

go deeper

for a junior

Know the one-liner: Bus = broker linking instances so one busrefresh call refreshes the whole cluster.

for a middle

Be able to name the starters, the default springCloudBus topic, and the exposure config for the Actuator endpoint.

for a senior

Explain that it's built on Spring Cloud Stream and carries RefreshRemoteApplicationEvent, plus the refresh vs busrefresh distinction.

for a principal

Position the Bus in the config-propagation architecture and know its limits — it's a control-plane broadcast, not a domain-event system.

## The problem In a microservice system you often run many instances of the same service. Spring Cloud Config lets those instances load configuration from a central Git-backed Config Server. But configuration is read at startup (and cached). When you change a property in the config repo, running instances don't see it automatically. Spring Boot Actuator gives each instance a `/actuator/refresh` endpoint: POST to it and that **one** instance re-reads its configuration and rebinds beans annotated with `@RefreshScope` and `@ConfigurationProperties`. The pain: with 30 instances you'd have to call `/actuator/refresh` 30 times, and you'd need to know every instance's address. ## What Spring Cloud Bus adds The Bus links all instances together over a shared **message broker** — either **RabbitMQ** or **Apache Kafka**. Think of it as an event backbone connecting every node. Instead of calling refresh per-instance: 1. you POST **once** to `/actuator/busrefresh` on any single instance; 2. that instance publishes a `RefreshRemoteApplicationEvent` onto the broker; 3. every instance subscribed to the Bus receives it and performs a local refresh. One call, whole cluster refreshed. ## How it's wired The Bus is implemented on top of **Spring Cloud Stream** — it does not talk to the broker directly, it uses a Stream binder. All instances share a single broker destination (a Kafka topic / Rabbit exchange) named **`springCloudBus`** by default. Messages carry `RemoteApplicationEvent` subclasses. ## Getting it running 1. Add one starter — `spring-cloud-starter-bus-amqp` (RabbitMQ) or `spring-cloud-starter-bus-kafka` — 2. and point it at a reachable broker (e.g. `spring.rabbitmq.host` / `spring.kafka.bootstrap-servers`). 3. Because `busrefresh` is an Actuator endpoint, you must **expose** it: `management.endpoints.web.exposure.include=busrefresh`. Then any config change followed by one `POST /actuator/busrefresh` reaches the whole fleet. ## Beyond refresh The same event backbone also carries `EnvironmentChangeRemoteApplicationEvent` (via the `/actuator/busenv` endpoint, which pushes a single property to the cluster) and optional acknowledgement/trace events. But config refresh is by far the headline use case. ## When to use it - Use the Bus when you have many instances and want cluster-wide, low-friction config refresh (or lightweight state-change broadcasts). - If you have a single instance, plain `/actuator/refresh` is enough and the Bus is overkill. - The Bus is not a general application messaging system — for domain events use Spring Cloud Stream / a broker directly.

  • How is /actuator/busrefresh different from /actuator/refresh?
    /actuator/refresh refreshes only the single instance you call. /actuator/busrefresh publishes a RefreshRemoteApplicationEvent onto the broker so every instance connected to the Bus refreshes — one call fans out to the whole cluster.
  • Which brokers does Spring Cloud Bus support?
    RabbitMQ (via spring-cloud-starter-bus-amqp) and Apache Kafka (via spring-cloud-starter-bus-kafka). It uses Spring Cloud Stream binders underneath, so the broker choice is just which starter/binder you include.

saying these in an interview costs you the question

  • Thinking the Bus talks to the broker directly rather than through Spring Cloud Stream
  • Believing busrefresh restarts the application (it only re-reads config and rebinds beans)
  • Assuming the Bus itself stores or serves configuration (that's the Config Server; the Bus only broadcasts the refresh signal)

context

open as a page

What exactly happens when you POST to /actuator/busrefresh, and which event is broadcast?

level: middleimportance: must knowfreq 50%

basics

~20 s

The instance you call publishes a RefreshRemoteApplicationEvent onto the shared broker topic. Every instance on the Bus receives it and does a local refresh — re-reading config and rebinding @RefreshScope / @ConfigurationProperties beans, exactly like calling /actuator/refresh on each one.

open as a page

What dependencies and configuration are required to enable Spring Cloud Bus refresh in a service?

level: middleimportance: should knowfreq 30%

basics

~10 s

Add one broker starter — spring-cloud-starter-bus-amqp (RabbitMQ) or spring-cloud-starter-bus-kafka — plus Actuator, point the app at a running broker, and expose the endpoint with management.endpoints.web.exposure.include=busrefresh. Then POST /actuator/busrefresh.

open as a page

How does Spring Cloud Bus use Spring Cloud Stream, and how does it ensure the event reaches every instance rather than just one?

level: seniorimportance: should knowfreq 35%

basics

~20 s

The Bus doesn't talk to the broker directly — it rides on Spring Cloud Stream, publishing to a shared destination called springCloudBus. To broadcast (not load-balance) it gives each instance a distinct identity (spring.cloud.bus.id) so every instance receives its own copy of the event.

open as a page

As an architect, how would you automate cluster-wide config propagation with the Bus, and what are its trade-offs versus alternatives at scale?

level: principalimportance: nice to knowfreq 20%

basics

~20 s

Instead of curling busrefresh by hand, wire the Config Server's git webhook to spring-cloud-config-monitor so a push auto-fires the Bus refresh. Trade-offs: you add broker infrastructure, get eventual (not atomic) propagation, and no strong ordering — fine for config, not for critical coordination.

open as a page