{"id":3708,"date":"2025-11-24T10:00:18","date_gmt":"2025-11-24T15:00:18","guid":{"rendered":"https:\/\/www.mymiller.name\/wordpress\/?p=3708"},"modified":"2025-11-24T10:00:18","modified_gmt":"2025-11-24T15:00:18","slug":"dynamic-feature-toggling-in-spring-microservices-with-spring-cloud-bus","status":"publish","type":"post","link":"https:\/\/www.mymiller.name\/wordpress\/spring_cloud_bus\/dynamic-feature-toggling-in-spring-microservices-with-spring-cloud-bus\/","title":{"rendered":"Dynamic Feature Toggling in Spring Microservices with Spring Cloud Bus"},"content":{"rendered":"\n<div class=\"wp-block-jetpack-markdown\"><h2>Dynamic Feature Toggles with Spring Cloud Bus<\/h2>\n<p>Feature toggles (or feature flags) are a powerful technique for managing application behavior without code deployments. They allow you to turn features on or off dynamically, enabling techniques like A\/B testing, canary releases, and kill switches. In this blog post, we\u2019ll explore how to implement dynamic feature toggles in a Spring Boot application using Spring Cloud Bus.<\/p>\n<p><strong>Why Spring Cloud Bus?<\/strong><\/p>\n<p>Spring Cloud Bus provides a lightweight communication channel between different instances of a Spring Boot application. This makes it ideal for propagating feature toggle updates across a distributed system. When a toggle changes in one instance, the change can be broadcast to all other instances via the bus, ensuring consistency.<\/p>\n<p><strong>Implementation<\/strong><\/p>\n<p>Let\u2019s break down the implementation into three parts: the <code>Toggle<\/code> entity, the <code>ToggleService<\/code>, and the <code>ToggleClient<\/code>.<\/p>\n<p><strong>1. The <code>Toggle<\/code> Entity<\/strong><\/p>\n<p>This simple entity represents a feature toggle:<\/p>\n<pre><code class=\"language-java\">import javax.persistence.Entity;\nimport javax.persistence.GeneratedValue;\nimport javax.persistence.GenerationType;\nimport javax.persistence.Id;\n\n@Entity\npublic class Toggle {\n\n    @Id\n    @GeneratedValue(strategy = GenerationType.IDENTITY)\n    private Long id;\n    private String key;\n    private boolean enabled;\n\n    \/\/ Getters and setters\n}\n<\/code><\/pre>\n<p><strong>2. The <code>ToggleService<\/code><\/strong><\/p>\n<p>This service provides CRUD operations for toggles and publishes updates via Spring Cloud Bus:<\/p>\n<pre><code class=\"language-java\">import org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.context.ApplicationEventPublisher;\nimport org.springframework.stereotype.Service;\n\nimport java.util.List;\n\n@Service\npublic class ToggleService {\n\n    @Autowired\n    private ToggleRepository toggleRepository;\n\n    @Autowired\n    private ApplicationEventPublisher eventPublisher;\n\n    public Toggle createToggle(Toggle toggle) {\n        Toggle createdToggle = toggleRepository.save(toggle);\n        publishToggleUpdates();\n        return createdToggle;\n    }\n\n    public Toggle updateToggle(Long id, Toggle toggle) {\n        Toggle existingToggle = toggleRepository.findById(id)\n                .orElseThrow(() -&gt; new RuntimeException(&quot;Toggle not found with id: &quot; + id));\n        existingToggle.setKey(toggle.getKey());\n        existingToggle.setEnabled(toggle.isEnabled());\n        Toggle updatedToggle = toggleRepository.save(existingToggle);\n        publishToggleUpdates();\n        return updatedToggle;\n    }\n\n    public void deleteToggle(Long id) {\n        toggleRepository.deleteById(id);\n        publishToggleUpdates();\n    }\n\n    public Toggle getToggle(Long id) {\n        return toggleRepository.findById(id)\n                .orElseThrow(() -&gt; new RuntimeException(&quot;Toggle not found with id: &quot; + id));\n    }\n\n    public List&lt;Toggle&gt; getAllToggles() {\n        return toggleRepository.findAll();\n    }\n\n    @EventListener\n    public void handleToggleUpdateRequest(RemoteApplicationEvent event) {\n        if (event instanceof ToggleUpdateRequest) { \n            publishToggleUpdates();\n        }\n    }\n\n    private void publishToggleUpdates() {\n        List&lt;Toggle&gt; toggles = toggleRepository.findAll();\n        eventPublisher.publishEvent(new ToggleUpdatedEvent(this, null, toggles));\n    }\n}\n<\/code><\/pre>\n<p><strong>3. The <code>ToggleClient<\/code><\/strong><\/p>\n<p>This service listens for toggle updates and provides a method to check if a toggle is enabled:<\/p>\n<pre><code class=\"language-java\">import org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.context.ApplicationEventPublisher;\nimport org.springframework.context.event.EventListener;\nimport org.springframework.stereotype.Service;\n\nimport javax.annotation.PostConstruct;\nimport java.util.ArrayList;\nimport java.util.List;\n\n@Service\npublic class ToggleClient {\n\n    private List&lt;Toggle&gt; toggles = new ArrayList&lt;&gt;();\n\n    @Autowired\n    private ApplicationEventPublisher eventPublisher;\n\n    @PostConstruct\n    public void requestToggleUpdatesOnStartup() {\n        sendToggleUpdateRequest();\n    }\n\n    public void sendToggleUpdateRequest() {\n        eventPublisher.publishEvent(new ToggleUpdateRequest(this, null));\n    }\n\n    @EventListener\n    public void handleToggleUpdates(ToggleUpdatedEvent event) {\n        this.toggles = event.getToggles();\n        System.out.println(&quot;Received updated toggles: &quot; + toggles);\n    }\n\n    public List&lt;Toggle&gt; getToggles() {\n        return toggles;\n    }\n\n    public boolean isToggleEnabled(String key) {\n        return toggles.stream()\n                .filter(toggle -&gt; toggle.getKey().equals(key))\n                .findFirst()\n                .map(Toggle::isEnabled)\n                .orElse(false);\n    }\n}\n<\/code><\/pre>\n<p><strong>Custom Events<\/strong><\/p>\n<p>We also need two custom events for communication over the bus:<\/p>\n<pre><code class=\"language-java\">import org.springframework.cloud.bus.event.RemoteApplicationEvent;\n\npublic class ToggleUpdateRequest extends RemoteApplicationEvent {\n    public ToggleUpdateRequest(Object source, String originService) {\n        super(source, originService);\n    }\n}\n\nimport org.springframework.cloud.bus.event.RemoteApplicationEvent;\nimport java.util.List;\n\npublic class ToggleUpdatedEvent extends RemoteApplicationEvent {\n\n    private List&lt;Toggle&gt; toggles;\n\n    public ToggleUpdatedEvent(Object source, String originService, List&lt;Toggle&gt; toggles) {\n        super(source, originService);\n        this.toggles = toggles;\n    }\n\n    public List&lt;Toggle&gt; getToggles() {\n        return toggles;\n    }\n}\n<\/code><\/pre>\n<p><strong>Putting it all together<\/strong><\/p>\n<p>With this setup, you can now dynamically manage feature toggles in your Spring Boot application. The <code>ToggleService<\/code> allows you to create, update, and delete toggles, while the <code>ToggleClient<\/code> keeps track of the latest toggle state and provides a convenient method to check if a toggle is enabled. Spring Cloud Bus ensures that all instances of your application are synchronized with the latest toggle configuration.<\/p>\n<p>This is a basic implementation, and you can extend it further by adding features like user-specific toggles, versioning, and audit trails.<\/p>\n<\/div>\n\n\n\n<div class=\"wp-block-jetpack-markdown\"><h3>Benefits<\/h3>\n<ul>\n<li><strong>Real-time updates:<\/strong> Changes to toggles are propagated instantly to all microservices.<\/li>\n<li><strong>Centralized management:<\/strong>  Provides a single point of control for managing all feature toggles.<\/li>\n<li><strong>Improved development workflow:<\/strong> Enables continuous delivery and deployment by decoupling feature releases from code deployments.<\/li>\n<li><strong>Reduced risk:<\/strong> Allows for gradual rollout of features and easy rollback if issues arise.<\/li>\n<\/ul>\n<p>This setup provides a robust and flexible foundation for implementing feature toggles in your Spring Boot microservices. You can further enhance it with features like:<\/p>\n<ul>\n<li><strong>User segmentation:<\/strong> Target specific user groups with different toggles.<\/li>\n<li><strong>Permissions:<\/strong> Control who can create, update, or delete toggles.<\/li>\n<li><strong>Audit logging:<\/strong> Track changes made to toggles.<\/li>\n<li><strong>UI:<\/strong> Build a user interface for easier toggle management.<\/li>\n<\/ul>\n<p>By leveraging the power of Spring Cloud Bus and a well-designed toggle service, you can gain greater control over your application\u2019s features and improve your development process.<\/p>\n<\/div>\n","protected":false},"excerpt":{"rendered":"","protected":false},"author":1,"featured_media":3709,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_coblocks_attr":"","_coblocks_dimensions":"","_coblocks_responsive_height":"","_coblocks_accordion_ie_support":"","jetpack_post_was_ever_published":false,"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_publicize_message":"","jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":true,"jetpack_social_options":{"image_generator_settings":{"template":"highway","default_image_id":0,"font":"","enabled":false},"version":2}},"categories":[437],"tags":[69,319],"series":[],"class_list":["post-3708","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-spring_cloud_bus","tag-java-2","tag-spring"],"jetpack_publicize_connections":[],"jetpack_featured_media_url":"https:\/\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2024\/09\/switches-923072_1280-jpg.avif","jetpack-related-posts":[{"id":3438,"url":"https:\/\/www.mymiller.name\/wordpress\/spring\/architecting-with-spring-and-spring-cloud\/","url_meta":{"origin":3708,"position":0},"title":"Architecting with Spring and Spring Cloud","author":"Jeffery Miller","date":"December 24, 2025","format":false,"excerpt":"Building a Multi-Service Architecture with Spring 3.1.x and Spring Cloud: Unlocking the Power of Microservices In the ever-evolving landscape of software development, microservices have emerged as a powerful architectural paradigm, enabling organizations to build scalable, resilient, and agile applications. Spring, a widely adopted Java framework, provides a comprehensive suite of\u2026","rel":"","context":"In &quot;Spring&quot;","block_context":{"text":"Spring","link":"https:\/\/www.mymiller.name\/wordpress\/category\/spring\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2023\/11\/field-5236879_640.jpg?fit=640%2C360&ssl=1&resize=350%2C200","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2023\/11\/field-5236879_640.jpg?fit=640%2C360&ssl=1&resize=350%2C200 1x, https:\/\/i0.wp.com\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2023\/11\/field-5236879_640.jpg?fit=640%2C360&ssl=1&resize=525%2C300 1.5x"},"classes":[]},{"id":3441,"url":"https:\/\/www.mymiller.name\/wordpress\/spring_discovery\/spring-cloud-gateway-with-spring-cloud-discovery\/","url_meta":{"origin":3708,"position":1},"title":"Spring Cloud Gateway with Spring Cloud Discovery","author":"Jeffery Miller","date":"December 24, 2025","format":false,"excerpt":"Spring Cloud Gateway and Spring Cloud Discovery are powerful tools for building microservices architectures. Spring Cloud Gateway acts as an API gateway, routing requests to the appropriate microservices. Spring Cloud Discovery provides a registry for microservices, enabling dynamic service discovery and load balancing. In this comprehensive guide, we'll delve into\u2026","rel":"","context":"In &quot;Spring Discovery&quot;","block_context":{"text":"Spring Discovery","link":"https:\/\/www.mymiller.name\/wordpress\/category\/spring_discovery\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2023\/11\/trees-2900064_640.jpg?fit=640%2C427&ssl=1&resize=350%2C200","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2023\/11\/trees-2900064_640.jpg?fit=640%2C427&ssl=1&resize=350%2C200 1x, https:\/\/i0.wp.com\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2023\/11\/trees-2900064_640.jpg?fit=640%2C427&ssl=1&resize=525%2C300 1.5x"},"classes":[]},{"id":3712,"url":"https:\/\/www.mymiller.name\/wordpress\/spring_events\/spring-into-action-with-spring-events-a-comprehensive-guide\/","url_meta":{"origin":3708,"position":2},"title":"Spring into Action with Spring Events: A Comprehensive Guide","author":"Jeffery Miller","date":"November 24, 2025","format":false,"excerpt":"Spring Framework offers a robust event handling mechanism that allows different parts of your application to communicate asynchronously. This is crucial for building loosely coupled and responsive applications, especially in a microservices architecture. This blog post will delve into Spring events, covering creation, publishing, and handling, both within a single\u2026","rel":"","context":"In &quot;Spring Events&quot;","block_context":{"text":"Spring Events","link":"https:\/\/www.mymiller.name\/wordpress\/category\/spring_events\/"},"img":{"alt_text":"","src":"https:\/\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2024\/09\/mailbox-2462122_1280-jpg.avif","width":350,"height":200,"srcset":"https:\/\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2024\/09\/mailbox-2462122_1280-jpg.avif 1x, https:\/\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2024\/09\/mailbox-2462122_1280-jpg.avif 1.5x, https:\/\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2024\/09\/mailbox-2462122_1280-jpg.avif 2x, https:\/\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2024\/09\/mailbox-2462122_1280-jpg.avif 3x"},"classes":[]},{"id":3444,"url":"https:\/\/www.mymiller.name\/wordpress\/spring_discovery\/spring-boot-admin-server-with-spring-cloud-discovery\/","url_meta":{"origin":3708,"position":3},"title":"Spring Boot Admin Server with Spring Cloud Discovery","author":"Jeffery Miller","date":"December 24, 2025","format":false,"excerpt":"Spring Boot Admin Server is a powerful tool for monitoring and managing Spring Boot applications. It provides a centralized dashboard for viewing application health, metrics, and logs. Spring Cloud Discovery, on the other hand, enables service registration and discovery for microservices-based applications. By integrating Spring Boot Admin Server with Spring\u2026","rel":"","context":"In &quot;Spring Discovery&quot;","block_context":{"text":"Spring Discovery","link":"https:\/\/www.mymiller.name\/wordpress\/category\/spring_discovery\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2023\/11\/manhattan-3866140_640.jpg?fit=640%2C427&ssl=1&resize=350%2C200","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2023\/11\/manhattan-3866140_640.jpg?fit=640%2C427&ssl=1&resize=350%2C200 1x, https:\/\/i0.wp.com\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2023\/11\/manhattan-3866140_640.jpg?fit=640%2C427&ssl=1&resize=525%2C300 1.5x"},"classes":[]},{"id":3928,"url":"https:\/\/www.mymiller.name\/wordpress\/spring_databases\/%f0%9f%92%a1-implementing-cqrs-with-spring-boot-and-kafka\/","url_meta":{"origin":3708,"position":4},"title":"\ud83d\udca1 Implementing CQRS with Spring Boot and Kafka","author":"Jeffery Miller","date":"November 21, 2025","format":false,"excerpt":"As a software architect, I constantly look for patterns that enhance the scalability and maintainability of microservices. The Command Query Responsibility Segregation (CQRS) pattern is a powerful tool for this, especially when coupled with event-driven architecture (EDA) using Apache Kafka. CQRS separates the application into two distinct models: one for\u2026","rel":"","context":"In &quot;Spring Databases&quot;","block_context":{"text":"Spring Databases","link":"https:\/\/www.mymiller.name\/wordpress\/category\/spring_databases\/"},"img":{"alt_text":"","src":"https:\/\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2025\/11\/data-2899902_1280.avif","width":350,"height":200,"srcset":"https:\/\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2025\/11\/data-2899902_1280.avif 1x, https:\/\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2025\/11\/data-2899902_1280.avif 1.5x, https:\/\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2025\/11\/data-2899902_1280.avif 2x, https:\/\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2025\/11\/data-2899902_1280.avif 3x"},"classes":[]},{"id":3754,"url":"https:\/\/www.mymiller.name\/wordpress\/spring_discovery\/conquering-distance-federated-service-discovery-with-spring-cloud-and-consul\/","url_meta":{"origin":3708,"position":5},"title":"Conquering Distance: Federated Service Discovery with Spring Cloud and Consul","author":"Jeffery Miller","date":"December 23, 2025","format":false,"excerpt":"Microservices excel at breaking down monolithic applications into smaller, manageable units. But as your system expands across multiple data centers or cloud providers, a new challenge emerges: how do services discover each other across these geographical boundaries? Traditional service discovery, with a single registry, can struggle with latency and fault\u2026","rel":"","context":"In &quot;Spring Discovery&quot;","block_context":{"text":"Spring Discovery","link":"https:\/\/www.mymiller.name\/wordpress\/category\/spring_discovery\/"},"img":{"alt_text":"","src":"https:\/\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2024\/10\/network-6564511_1280-jpg.avif","width":350,"height":200,"srcset":"https:\/\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2024\/10\/network-6564511_1280-jpg.avif 1x, https:\/\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2024\/10\/network-6564511_1280-jpg.avif 1.5x, https:\/\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2024\/10\/network-6564511_1280-jpg.avif 2x, https:\/\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2024\/10\/network-6564511_1280-jpg.avif 3x"},"classes":[]}],"jetpack_sharing_enabled":true,"jetpack_likes_enabled":true,"_links":{"self":[{"href":"https:\/\/www.mymiller.name\/wordpress\/wp-json\/wp\/v2\/posts\/3708","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.mymiller.name\/wordpress\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.mymiller.name\/wordpress\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.mymiller.name\/wordpress\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.mymiller.name\/wordpress\/wp-json\/wp\/v2\/comments?post=3708"}],"version-history":[{"count":1,"href":"https:\/\/www.mymiller.name\/wordpress\/wp-json\/wp\/v2\/posts\/3708\/revisions"}],"predecessor-version":[{"id":3711,"href":"https:\/\/www.mymiller.name\/wordpress\/wp-json\/wp\/v2\/posts\/3708\/revisions\/3711"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.mymiller.name\/wordpress\/wp-json\/wp\/v2\/media\/3709"}],"wp:attachment":[{"href":"https:\/\/www.mymiller.name\/wordpress\/wp-json\/wp\/v2\/media?parent=3708"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.mymiller.name\/wordpress\/wp-json\/wp\/v2\/categories?post=3708"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.mymiller.name\/wordpress\/wp-json\/wp\/v2\/tags?post=3708"},{"taxonomy":"series","embeddable":true,"href":"https:\/\/www.mymiller.name\/wordpress\/wp-json\/wp\/v2\/series?post=3708"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}