Skip to content

Microswitch - Advanced Embedded Deployment Strategy Library A powerful Java Spring Boot library for implementing sophisticated deployment strategies with real-time traffic management on low level and deep result comparison.

License

Notifications You must be signed in to change notification settings

n11techhub/microswitch

🚀 Microswitch — Deployment Strategy Library

License

Microswitch is a lightweight library for Java/Spring Boot that lets you apply deployment strategies programmatically: Canary, Shadow, and Blue/Green. It provides a single, minimal public API and hides all internals via JPMS.

This README explains how to add Microswitch to your project, configure it, and use it safely in production.

Table of Contents

Features

  • Canary, Shadow, and Blue/Green strategies
  • Lazy evaluation (only the selected Supplier executes)
  • Optional Prometheus/Micrometer metrics
  • YAML-based configuration
  • Spring Boot auto-configuration
  • Actuator endpoint for runtime visibility

Requirements

  • Java 21+
  • Spring Boot 3.5.5+

Installation

Option 1: JitPack (No Authentication Required) ⭐ Recommended

Maven

<repositories>
    <repository>
        <id>jitpack.io</id>
        <url>https://jitpack.io</url>
    </repository>
</repositories>

<dependency>
    <groupId>com.github.n11tech</groupId>
    <artifactId>microswitch</artifactId>
    <version>v1.4.8</version>  <!-- JitPack uses tag name with 'v' prefix -->
</dependency>

Gradle

repositories {
    maven { url 'https://jitpack.io' }
}

dependencies {
    implementation 'com.github.n11tech:microswitch:v1.4.8'  // JitPack uses tag name with 'v' prefix
}

Option 2: GitHub Packages (Authentication Required)

First, configure authentication in ~/.m2/settings.xml:

<settings>
  <servers>
    <server>
      <id>github</id>
      <username>YOUR_GITHUB_USERNAME</username>
      <password>YOUR_GITHUB_TOKEN</password>
    </server>
  </servers>
</settings>

Then add to your project:

Maven

<repositories>
    <repository>
        <id>github</id>
        <url>https://maven.pkg.github.com/n11tech/microswitch</url>
    </repository>
</repositories>

<dependency>
    <groupId>io.github.n11tech</groupId>
    <artifactId>microswitch</artifactId>
    <version>1.4.8</version>
</dependency>

Gradle

repositories {
    maven {
        url = uri("https://maven.pkg.github.com/n11tech/microswitch")
        credentials {
            username = project.findProperty("gpr.user") ?: System.getenv("USERNAME")
            password = project.findProperty("gpr.key") ?: System.getenv("TOKEN")
        }
    }
}

dependencies {
    implementation 'io.github.n11tech:microswitch:1.4.8'
}

Quick Start

  1. Configure application properties (application.yml)
microswitch:
  enabled: true                       # master switch
  services:
    user-service:
      enabled: true
      activeStrategy: canary          # NEW in v1.1.0: configuration-driven strategy selection
      canary:
        percentage: 80/20             # stable/experimental split
        algorithm: SEQUENCE           # AlgorithmType enum (e.g., SEQUENCE, RANDOM)
      blueGreen:
        weight: 1/0                   # 1/0 → primary, 0/1 → secondary
        ttl: 60000                    # milliseconds
      shadow:
        stable: primary               # returns result from this path
        mirror: secondary             # mirrors this path when triggered
        mirrorPercentage: 10          # mirror every 10% of calls
        comparator:                   # NEW in v1.2.2: nested comparator tuning
          mode: disable               # enable/disable deep comparison
          maxCompareTimeMillis: 200
          samplingOnHuge:
            enable: false             # enable sampling for large collections
            maxCollectionElements: 1000
            stride: 10
          maxFieldsPerClass: 100
  1. Inject and use DeploymentManager
@Service
public class UserService {

  private final DeploymentManager deploymentManager;

  public UserService(DeploymentManager deploymentManager) {
    this.deploymentManager = deploymentManager;
  }

  public User createUser(String name) {
    // NEW in v1.1.0: Configuration-driven strategy selection
    return deploymentManager.execute(
        () -> createUserV1(name),  // stable
        () -> createUserV2(name),  // experimental
        "user-service"             // uses activeStrategy from config
    );
    
    // Legacy approach (still supported but deprecated)
    // return deploymentManager.canary(() -> createUserV1(name), () -> createUserV2(name), "user-service");
  }

  private User createUserV1(String name) { return new User(name, "v1"); }
  private User createUserV2(String name) { return new User(name, "v2"); }
}

Deployment Strategies

Canary

Route a percentage of traffic to the experimental version.

// %80 stable, %20 experimental
String result = deploymentManager.canary(
    this::stableMethod,
    this::experimentalMethod,
    "service-key"
);

Shadow

Execute the experimental path in the background, but always return the stable result to callers. Useful for validating parity and measuring performance.

// Stable döner, experimental paralel çalışır
Integer result = deploymentManager.shadow(
    this::stableMethod,
    this::experimentalMethod,
    "service-key"
);

Blue/Green

Choose between two versions using a binary weight selector and/or a TTL cutoff for full switchover. The weight accepts only two forms:

  • 1/0 → route to primary
  • 0/1 → route to secondary
// Primary percentage veya TTL tabanlı seçim
String result = deploymentManager.blueGreen(
    this::blueMethod,
    this::greenMethod,
    "service-key"
);

Release Notes

See the full changelog here: CHANGELOG.md

Version 1.4.8 (Latest)

New in 1.4.8 — JitPack Build Fixes

  • Fixed: JitPack build issues with Java 21 and JPMS modules
  • Added: jitpack.yml configuration to ensure OpenJDK 21 is used
  • Updated: Maven compiler plugin configuration for better compatibility

New in 1.4.7 — GroupId Migration and JitPack Support

See CHANGELOG.md for complete details. Major changes include:

  • Breaking Change: Maven GroupId changed from io.development.n11tech to io.github.n11tech
  • JitPack Support: Now available via JitPack without authentication requirement
  • Simplified Workflow: Removed complex version checking from GitHub Actions

Carried over from 1.4.6 — Enhanced Stability and Performance

  1. Comparator tuning for large data structures (Shadow strategy)
microswitch:
  services:
    order-service:
      shadow:
        comparator:
          mode: enable               # enable/disable deep comparison
          maxCompareTimeMillis: 200      # time budget in ms; returns early when exceeded
          samplingOnHuge:
            enable: false            # enable sampling mode for huge lists
            maxCollectionElements: 1000   # switch to sampling for very large lists
            stride: 10               # sampling step for lists
          maxFieldsPerClass: 100
  • Large lists: head/tail + stride sampling prevents O(n) deep scans
  • Time budget: early return if the total comparison time exceeds the configured budget
  1. Operational visibility with WARN logs
  • Sampling activated: Deep comparison sampling activated for large list (size=...)
  • Time budget exceeded: Deep comparison time budget exceeded (>X ms) at ... after Y ms; returning early

These logs make performance-protection behavior observable in production without extra instrumentation.

  1. Backward compatibility
  • Legacy shadow.comparator: enable|disable still works and maps to shadow.comparator.mode
  • New nested fields are optional and come with safe defaults

Improvements carried over from 1.1.2

  • Enhanced constructor injection in auto-configuration
  • Improved logging and configuration validation

Bug Fixes & Improvements

1. Enhanced Constructor Injection

Improved dependency injection reliability by replacing field injection with constructor injection in MicroswitchAutoConfiguration:

// Before: Field injection with @Autowired
@Autowired
private InitializerConfiguration properties;

// After: Constructor injection (more reliable)
public MicroswitchAutoConfiguration(InitializerConfiguration properties) {
    this.properties = properties;
}

Benefits:

  • More reliable dependency injection
  • Better testability and immutability
  • Follows Spring Boot best practices
  • Eliminates potential null pointer exceptions
2. Improved Logging and Error Handling

Enhanced logging throughout the library for better debugging and monitoring:

  • Added detailed initialization logging based on enabled/disabled state
  • Improved error messages for configuration validation
  • Enhanced debug logging for strategy execution paths
  • Better exception handling with more descriptive error messages
3. Configuration Validation Improvements

Strengthened configuration validation and error reporting:

  • Better validation messages for invalid strategy configurations
  • Improved handling of missing or malformed configuration sections
  • Enhanced fallback mechanisms for edge cases

Benefits

  • Better Reliability: Constructor injection eliminates potential initialization issues
  • Enhanced Debugging: Improved logging helps identify configuration and execution issues
  • Stronger Validation: Better error messages and validation for configuration problems
  • Maintainability: Code follows Spring Boot best practices

Version 1.1.2

New Features

1. Execution Logging

Detailed execution logging to track service key, strategy, and method execution:

microswitch:
  logger: enable  # Enable detailed execution logging (default: disable)

When enabled, logs include:

  • [MICROSWITCH-EXEC] Starting execution - Service: 'X', Strategy: 'Y'
  • [MICROSWITCH-EXEC] Executing - Service: 'X', Strategy: 'Y', Method: 'stable/experimental'
  • [MICROSWITCH-EXEC] Completed - Service: 'X', Strategy: 'Y', Method: 'Z' (Success)
  • [MICROSWITCH-EXEC] Failed - Service: 'X', Strategy: 'Y', Method: 'Z' - Error: ...
2. Deep Object Comparison for Shadow Strategy

Configurable deep object comparison for shadow traffic validation:

microswitch:
  services:
    order-service:
      shadow:
        comparator: enable  # Enable deep object comparison (default: disable)

When enabled:

  • Compares objects by field values rather than reference equality
  • Supports nested objects, collections, maps, and arrays
  • Uses HYBRID strategy: checks for overridden equals() first, falls back to field comparison
  • Automatically ignores common tracking fields (timestamp, requestId, traceId)
3. Bean Availability When Disabled

Fixed dependency injection issues when microswitch is disabled:

microswitch:
  enabled: false  # DeploymentManager bean is still available for injection

Problem Solved: Previously, when microswitch.enabled=false, the DeploymentManager bean was not created, causing Spring Boot applications to fail with:

Parameter 2 of constructor required a bean of type 'DeploymentManager' that could not be found

Solution: The DeploymentManager bean is now always created regardless of the enabled setting:

  • When enabled: true: Full functionality with all strategies available
  • When enabled: false: Bean is available but strategies are disabled internally
  • Applications can safely inject DeploymentManager without startup failures
  • Runtime logging clearly indicates the enabled/disabled state

Benefits

  • Better Observability: Track exactly which service, strategy, and method are executing
  • Accurate Shadow Validation: Compare actual object content, not just references
  • Reliable Dependency Injection: No startup failures when microswitch is disabled
  • Zero Code Changes: All features are configuration-driven
  • Performance Optimized: No impact when disabled (default)

Version 1.1.0

  • Configuration-Driven Deployment: New execute() method for runtime strategy switching
  • Deprecated Legacy Methods: canary(), shadow(), blueGreen() marked for removal in v2.0.0
  • Active Strategy Configuration: Added activeStrategy field to service configuration

Configuration-Driven Deployment (New in v1.1.0)

Starting with version 1.1.0, Microswitch supports configuration-driven strategy selection using the new execute() method. This allows you to change deployment strategies at runtime without code changes.

Benefits

  • Runtime Strategy Switching: Change strategies via configuration updates without redeployment
  • Centralized Management: All strategy decisions in one place (application.yml)
  • Operational Flexibility: Switch from canary to blue-green to shadow based on operational needs
  • A/B Testing: Easy strategy comparison for the same service

Usage

// Configuration-driven approach (recommended)
String result = deploymentManager.execute(
    this::stableMethod,
    this::experimentalMethod,
    "service-key"  // Strategy determined by activeStrategy in config
);

Configuration

microswitch:
  services:
    payment-service:
      activeStrategy: canary    # Options: canary, shadow, blueGreen
      canary:
        percentage: 90/10
      shadow:
        mirrorPercentage: 20
      blueGreen:
        weight: 1/0
        ttl: 300000

Migration from Legacy Methods

The legacy strategy-specific methods (canary(), shadow(), blueGreen()) are still supported but deprecated:

// ❌ Deprecated (will be removed in v2.0.0)
deploymentManager.canary(stable, experimental, "service");

// ✅ Recommended (configuration-driven)
deploymentManager.execute(stable, experimental, "service");

Configuration

Full example

microswitch:
  enabled: true
  services:
    payment-service:
      enabled: true
      canary:
        percentage: 90/10          # 90% stable, 10% canary
        algorithm: SEQUENCE        # AlgorithmType enum value
      blueGreen:
        weight: 1/0                # 1/0 → primary, 0/1 → secondary
        ttl: 7200000               # 2 hours in ms
      shadow:
        stable: primary
        mirror: secondary
        mirrorPercentage: 20       # mirror 20% of the time
        comparator:
          mode: disable            # deep object comparison (enable/disable)
          maxCompareTimeMillis: 200
          samplingOnHuge:
            enable: false          # enable sampling for large collections
            maxCollectionElements: 1000
            stride: 10
          maxFieldsPerClass: 100

    user-service:
      enabled: false               # disabled — only stable executes

Parameters

Parameter Description Default
microswitch.logger NEW v1.1.1: Enable/disable detailed execution logging disable
microswitch.enabled Master switch for the library true
services.<key>.enabled Whether the service key is active true
services.<key>.activeStrategy NEW v1.1.0: Active strategy for configuration-driven deployment (canary, shadow, blueGreen) canary
services.<key>.canary.percentage Stable/experimental split in slash format (e.g., 80/20) or a single number meaning stable percentage 100
services.<key>.canary.algorithm AlgorithmType enum value (e.g., SEQUENCE, RANDOM) SEQUENCE
services.<key>.blueGreen.weight Binary selector in slash format: 1/0 (primary) or 0/1 (secondary) 1/0
services.<key>.blueGreen.ttl Time to live in milliseconds for route stickiness or switchover logic null
services.<key>.shadow.stable Which method is considered stable (primary or secondary) primary
services.<key>.shadow.mirror Which method is mirrored (primary or secondary) secondary
services.<key>.shadow.mirrorPercentage Percentage of calls that will trigger a mirror execution (0–100) 0
services.<key>.shadow.comparator.mode v1.2.2: Enable/disable deep object comparison for shadow validation disable
services.<key>.shadow.comparator.maxCompareTimeMillis v1.2.2: Time budget for deep comparison (ms) 200
services.<key>.shadow.comparator.samplingOnHuge.enable v1.2.2: Enable sampling mode for huge lists false
services.<key>.shadow.comparator.samplingOnHuge.maxCollectionElements v1.2.2: Threshold to activate sampling for large lists 1000
services.<key>.shadow.comparator.samplingOnHuge.stride v1.2.2: Sampling step for list comparison 10
services.<key>.shadow.comparator.maxFieldsPerClass v1.2.2: Maximum reflected fields per class (hard cap: 100) 100

Metrics & Actuator

Prometheus/Micrometer

If Micrometer is present and a MeterRegistry bean exists, Microswitch publishes counters per strategy/service/version automatically.

# HELP microswitch_success_total
# TYPE microswitch_success_total counter
microswitch_success_total{service="user-service",version="stable",strategy="canary"} 85
microswitch_success_total{service="user-service",version="experimental",strategy="canary"} 15

# HELP microswitch_error_total
# TYPE microswitch_error_total counter
microswitch_error_total{service="user-service",version="stable",strategy="canary"} 3
microswitch_error_total{service="user-service",version="experimental",strategy="canary"} 2

Prometheus setup (recommended)

Microswitch does not expose a custom Prometheus endpoint. Instead, use Spring Boot Actuator’s built-in /actuator/prometheus endpoint. This keeps the library backend-agnostic and simpler for developers.

  1. Add dependencies in the consuming app:
<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-actuator</artifactId>
  <scope>runtime</scope>
</dependency>
<dependency>
  <groupId>io.micrometer</groupId>
  <artifactId>micrometer-registry-prometheus</artifactId>
  <scope>runtime</scope>
</dependency>
  1. Expose the Prometheus endpoint:
management:
  endpoints:
    web:
      exposure:
        include: health,info,prometheus
  1. Configure Prometheus to scrape your service:
scrape_configs:
  - job_name: "microswitch"
    metrics_path: "/actuator/prometheus"
    static_configs:
      - targets: ["localhost:8080"]

Automatic metrics handling

Microswitch automatically provides a DeploymentMetrics bean in all scenarios:

  • With MeterRegistry (when Actuator + Prometheus registry are present): Real metrics are recorded and exposed at /actuator/prometheus
  • Without MeterRegistry: A no-operation implementation is used that safely ignores metric calls without errors

This ensures DeploymentStrategyExecutor never encounters null metrics, maintaining reliability across all deployment configurations.

  1. Example PromQL queries using Microswitch counters

Counters are registered as microswitch.success / microswitch.error and exposed to Prometheus as microswitch_success_total / microswitch_error_total with tags service, version, strategy.

# Per-service, per-strategy success rate (last 5 minutes)
sum by(service, strategy) (
  rate(microswitch_success_total[5m])
) /
sum by(service, strategy) (
  rate(microswitch_success_total[5m]) + rate(microswitch_error_total[5m])
)

# Canary-only success ratio
sum by(service) (
  rate(microswitch_success_total{strategy="canary"}[5m])
) /
sum by(service) (
  rate(microswitch_success_total{strategy="canary"}[5m]) + rate(microswitch_error_total{strategy="canary"}[5m])
)

# Shadow accuracy across stable/experimental
sum by(service) (
  rate(microswitch_success_total{strategy="shadow",version=~"stable|experimental"}[5m])
) /
sum by(service) (
  rate(microswitch_success_total{strategy="shadow",version=~"stable|experimental"}[5m]) +
  rate(microswitch_error_total{strategy="shadow",version=~"stable|experimental"}[5m])
)

Actuator Endpoint

# View current configuration
GET /actuator/microswitch

# Example response
{
  "services": {
    "user-service": {
      "enabled": true,
      "canary": {
        "primaryPercentage": 80,
        "algorithm": "random"
      }
    }
  }
}

Public API & Module Boundaries

Microswitch exposes a single public API surface: com.microswitch.infrastructure.manager.DeploymentManager.

With JPMS, only this package is exported. Internal packages (e.g., domain, application, infrastructure) are not exported and may change without notice. Even on the classpath, you should only call DeploymentManager.

  • Exported: com.microswitch.infrastructure.manager
  • Opened (for reflective access):
    • com.microswitch.application.config — Spring Boot auto-configuration
    • com.microswitch.infrastructure.external — Actuator endpoints

If you use JPMS (module-path), add Microswitch to your module-info.java:

module your.app.module {
  requires spring.boot;
  requires spring.boot.autoconfigure;
  requires io.github.n11tech.microswitch; // Microswitch public API
  // ... other requires
}

DeploymentManager

public class DeploymentManager {
    
    // Configuration-driven deployment (NEW in v1.1.0)
    public <R> R execute(Supplier<R> primary, Supplier<R> secondary, String serviceKey);
    
    // Legacy strategy-specific methods (deprecated in v1.1.0)
    @Deprecated(since = "1.1.0", forRemoval = true)
    public <R> R canary(Supplier<R> stable, Supplier<R> experimental, String serviceKey);
    
    @Deprecated(since = "1.1.0", forRemoval = true)
    public <R> R shadow(Supplier<R> stable, Supplier<R> experimental, String serviceKey);
    
    @Deprecated(since = "1.1.0", forRemoval = true)
    public <R> R blueGreen(Supplier<R> blue, Supplier<R> green, String serviceKey);
}

Supplier usage

// Method reference (recommended with new execute method)
deploymentManager.execute(this::methodV1, this::methodV2, "service");

// Lambda expression (configuration-driven)
deploymentManager.execute(
    () -> processPayment(request),
    () -> processPaymentNew(request),
    "payment"
);

// Legacy approach (deprecated)
// deploymentManager.canary(this::methodV1, this::methodV2, "service");

Examples

E-Commerce Payment

@Service
@Slf4j
public class PaymentService {
    
    @Autowired
    private DeploymentManager deploymentManager;
    
    public PaymentResult processPayment(PaymentRequest request) {
        // Configuration-driven approach (v1.1.0+)
        return deploymentManager.execute(
            () -> processWithOldProvider(request),
            () -> processWithNewProvider(request),
            "payment-processing"  // Strategy determined by activeStrategy in config
        );
    }
    
    private PaymentResult processWithOldProvider(PaymentRequest request) {
        log.info("Processing with legacy provider");
        // Legacy payment logic
        return PaymentResult.success("OLD_PROVIDER");
    }
    
    private PaymentResult processWithNewProvider(PaymentRequest request) {
        log.info("Processing with new provider");
        // New payment logic
        return PaymentResult.success("NEW_PROVIDER");
    }
}

User Authentication

@Service
public class AuthService {
    
    @Autowired
    private DeploymentManager deploymentManager;
    
    public boolean authenticateUser(String username, String password) {
        // Configuration-driven approach (v1.1.0+)
        return deploymentManager.execute(
            () -> authenticateWithLDAP(username, password),
            () -> authenticateWithOAuth(username, password),
            "user-auth"  // Strategy determined by activeStrategy in config
        );
    }
    
    // Shadow: returns LDAP result, mirrors OAuth in background
    private boolean authenticateWithLDAP(String username, String password) {
        // LDAP authentication
        return ldapService.authenticate(username, password);
    }
    
    private boolean authenticateWithOAuth(String username, String password) {
        // OAuth authentication (shadow testing)
        return oauthService.authenticate(username, password);
    }
}

Analytics

@Service
public class AnalyticsService {
    
    @Autowired
    private DeploymentManager deploymentManager;
    
    public AnalyticsReport generateReport(String userId) {
        // Configuration-driven approach (v1.1.0+)
        return deploymentManager.execute(
            () -> generateReportV1(userId),
            () -> generateReportV2(userId),
            "analytics-report"  // Strategy determined by activeStrategy in config
        );
    }
    
    // Blue/Green: fully switches to V2 after TTL
}

Best Practices

1) Service key naming

// ✅ İyi
"user-registration"
"payment-processing"
"order-fulfillment"

// ❌ Kötü
"service1"
"test"
"temp"

2) Use configuration-driven approach

// ✅ Recommended - Configuration-driven (v1.1.0+)
deploymentManager.execute(this::methodV1, this::methodV2, "service");

// ❌ Deprecated - Strategy-specific methods
deploymentManager.canary(this::methodV1, this::methodV2, "service");

3) Prefer method references

// ✅ Good - Lazy evaluation
deploymentManager.execute(this::methodV1, this::methodV2, "service");

// ❌ Bad - Eager evaluation
deploymentManager.execute(() -> methodV1(), () -> methodV2(), "service");

4) Error handling

public Result processData(String data) {
    try {
        return deploymentManager.execute(
            () -> processV1(data),
            () -> processV2(data),
            "data-processing"
        );
    } catch (Exception e) {
        log.error("Deployment failed, using fallback", e);
        return processV1(data); // Fallback to stable
    }
}

5) Monitoring

// Check metrics and configuration
@EventListener
public void onApplicationReady(ApplicationReadyEvent event) {
    log.info("Microswitch metrics at /actuator/prometheus");
    log.info("Microswitch config at /actuator/microswitch");
}

Troubleshooting

1) Bean not found

Error: No qualifying bean of type 'DeploymentManager'

Solution 1: If you're using an older version (< v1.1.1), add io.github.n11tech into your @ComponentScan:

@SpringBootApplication
@ComponentScan(basePackages = {"com.yourpackage", "io.github.n11tech"})
public class Application {
    // ...
}

Solution 2: If you're using v1.1.1+ and have microswitch.enabled=false, this issue is automatically resolved. The DeploymentManager bean is now always created regardless of the enabled setting. Simply ensure you have the correct version:

<dependency>
  <groupId>io.github.n11tech</groupId>
  <artifactId>microswitch</artifactId>
  <version>1.4.7</version>
</dependency>

2. Konfigürasyon Yüklenmiyor

Çözüm: application.yml dosyasında microswitch konfigürasyonunu kontrol edin.

3. Metrics Görünmüyor

Çözüm: Micrometer ve Actuator dependencies'lerini ekleyin:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
    <groupId>io.micrometer</groupId>
    <artifactId>micrometer-registry-prometheus</artifactId>
</dependency>

Debug Modu

logging:
  level:
    io.github.n11tech: DEBUG

Health Check

@Component
public class MicroswitchHealthCheck {
    
    @Autowired
    private DeploymentManager deploymentManager;
    
    @EventListener
    public void checkHealth(ApplicationReadyEvent event) {
        try {
            String result = deploymentManager.execute(
                () -> "healthy",
                () -> "healthy",
                "health-check"
            );
            log.info("Microswitch health check: {}", result);
        } catch (Exception e) {
            log.error("Microswitch health check failed", e);
        }
    }
}

JPMS Module-Info Usage

module com.example.microswitch {
    requires io.github.n11tech.microswitch;
    // ...
}

Performance Notes

  • Lazy evaluation: only the selected Supplier executes
  • Minimal overhead added to your call path
  • Thread-safe by design within strategy execution paths

Contributing & Governance

Please see:

Security

See SECURITY.md for how to report vulnerabilities.

License (Apache-2.0)

This project is licensed under the Apache License, Version 2.0. See the LICENSE file for details, or visit:

https://www.apache.org/licenses/LICENSE-2.0

Support

About

Microswitch - Advanced Embedded Deployment Strategy Library A powerful Java Spring Boot library for implementing sophisticated deployment strategies with real-time traffic management on low level and deep result comparison.

Resources

License

Code of conduct

Contributing

Security policy

Stars

Watchers

Forks

Packages

 
 
 

Languages