diff --git a/fallback/etc/fallback.urm.png b/fallback/etc/fallback.urm.png
new file mode 100644
index 000000000000..210a48724251
Binary files /dev/null and b/fallback/etc/fallback.urm.png differ
diff --git a/fallback/etc/fallback.urm.puml b/fallback/etc/fallback.urm.puml
new file mode 100644
index 000000000000..82e07903b953
--- /dev/null
+++ b/fallback/etc/fallback.urm.puml
@@ -0,0 +1,173 @@
+@startuml
+package fallback {
+  class App {
+    - TIMEOUT : int {static}
+    - MAX_ATTEMPTS : int {static}
+    - RETRY_DELAY : int {static}
+    - DEFAULT_API_URL : String {static}
+    - circuitBreaker : CircuitBreaker
+    - executor : ExecutorService
+    - fallbackService : Service
+    - primaryService : Service
+    - state : ExecutionState
+    - LOGGER : Logger {static}
+    + App()
+    + App(primaryService : Service, fallbackService : Service, circuitBreaker : CircuitBreaker)
+    + executeWithFallback() : String
+    - getFallbackData() : String
+    - updateFallbackCache(result : String)
+    + shutdown()
+    + main(args : String[]) {static}
+  }
+
+  interface Service {
+    + getData() : String
+  }
+
+  interface CircuitBreaker {
+    + isOpen() : boolean
+    + allowRequest() : boolean
+    + recordFailure()
+    + recordSuccess()
+    + reset()
+    + getState() : CircuitState
+  }
+
+  class DefaultCircuitBreaker {
+    - RESET_TIMEOUT : long {static}
+    - MIN_HALF_OPEN_DURATION : Duration {static}
+    - state : State
+    - failureThreshold : int
+    - lastFailureTime : long
+    - failureTimestamps : Queue<Long>
+    - windowSize : Duration
+    - halfOpenStartTime : Instant
+    + DefaultCircuitBreaker(failureThreshold : int)
+    + isOpen() : boolean
+    + allowRequest() : boolean
+    + recordFailure()
+    + recordSuccess()
+    + reset()
+    + getState() : CircuitState
+    - transitionToHalfOpen()
+    - enum State { CLOSED, OPEN, HALF_OPEN }
+  }
+
+  class FallbackService {
+    - {static} MAX_RETRIES : int = 3
+    - {static} RETRY_DELAY_MS : long = 1000
+    - {static} TIMEOUT : int = 2
+    - {static} MIN_SUCCESS_RATE : double = 0.6
+    - {static} MAX_REQUESTS_PER_MINUTE : int = 60
+    - {static} LOGGER : Logger
+    - primaryService : Service
+    - fallbackService : Service
+    - circuitBreaker : CircuitBreaker
+    - executor : ExecutorService
+    - healthChecker : ScheduledExecutorService
+    - monitor : ServiceMonitor
+    - rateLimiter : RateLimiter
+    - state : ServiceState
+    + FallbackService(primaryService : Service, fallbackService : Service, circuitBreaker : CircuitBreaker)
+    + getData() : String
+    - executeWithTimeout(task : Callable<String>) : String
+    - executeFallback() : String
+    - updateFallbackCache(result : String)
+    - startHealthChecker()
+    + close()
+    + getMonitor() : ServiceMonitor
+    + getState() : ServiceState
+    - enum ServiceState { STARTING, RUNNING, DEGRADED, CLOSED }
+  }
+
+  class LocalCacheService {
+    - cache : Cache<String, String>
+    - refreshExecutor : ScheduledExecutorService
+    - {static} CACHE_EXPIRY_MS : long = 300000
+    - {static} CACHE_REFRESH_INTERVAL : Duration = Duration.ofMinutes(5)
+    - {static} LOGGER : Logger
+    + LocalCacheService()
+    + getData() : String
+    + updateCache(key : String, value : String)
+    + close() : void
+    - initializeDefaultCache()
+    - scheduleMaintenanceTasks()
+    - cleanupExpiredEntries()
+    - enum FallbackLevel { PRIMARY, SECONDARY, TERTIARY }
+    - class Cache<K, V> {
+      - map : ConcurrentHashMap<K, CacheEntry<V>>
+      - expiryMs : long
+      + Cache(expiryMs : long)
+      + get(key : K) : V
+      + put(key : K, value : V)
+      + cleanup()
+      - record CacheEntry<V>(value : V, expiryTime : long) { + isExpired() : boolean }
+    }
+
+
+  class RemoteService {
+    - apiUrl : String
+    - httpClient : HttpClient
+    - {static} TIMEOUT_SECONDS : int = 2
+    + RemoteService(apiUrl : String, httpClient : HttpClient)
+    + getData() : String
+  }
+
+  class ServiceMonitor {
+    - successCount : AtomicInteger
+    - fallbackCount : AtomicInteger
+    - errorCount : AtomicInteger
+    - lastSuccessTime : AtomicReference<Instant>
+    - lastFailureTime : AtomicReference<Instant>
+    - lastResponseTime : AtomicReference<Duration>
+    - metrics : Queue<ServiceMetric>
+    - fallbackWeight : double
+    - metricWindow : Duration
+    + ServiceMonitor()
+    + ServiceMonitor(fallbackWeight : double, metricWindow : Duration)
+    + recordSuccess(responseTime : Duration)
+    + recordFallback()
+    + recordError()
+    + getSuccessCount() : int
+    + getFallbackCount() : int
+    + getErrorCount() : int
+    + getLastSuccessTime() : Instant
+    + getLastFailureTime() : Instant
+    + getLastResponseTime() : Duration
+    + getSuccessRate() : double
+    + reset()
+    - pruneOldMetrics()
+    - record ServiceMetric(timestamp : Instant, type : MetricType, responseTime : Duration)
+    - enum MetricType { SUCCESS, FALLBACK, ERROR }
+  }
+
+  class RateLimiter {
+    - maxRequests : int
+    - window : Duration
+    - requestTimestamps : Queue<Long>
+    + RateLimiter(maxRequests : int, window : Duration)
+    + tryAcquire() : boolean
+  }
+
+  class ServiceException {
+    + ServiceException(message : String)
+    + ServiceException(message : String, cause : Throwable)
+  }
+}
+  ' Relationships
+  App --> CircuitBreaker
+  App --> Service : primaryService
+  App --> Service : fallbackService
+  DefaultCircuitBreaker ..|> CircuitBreaker 
+  LocalCacheService ..|> Service 
+  RemoteService ..|> Service 
+  FallbackService ..|> Service
+  FallbackService ..|> AutoCloseable
+  FallbackService --> Service : primaryService
+  FallbackService --> Service : fallbackService
+  FallbackService --> CircuitBreaker
+  FallbackService --> ServiceMonitor
+  FallbackService --> RateLimiter
+  ServiceException --|> Exception
+}
+@enduml
\ No newline at end of file
diff --git a/fallback/pom.xml b/fallback/pom.xml
new file mode 100644
index 000000000000..23bf3df7e010
--- /dev/null
+++ b/fallback/pom.xml
@@ -0,0 +1,72 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).
+
+    The MIT License
+    Copyright © 2014-2022 Ilkka Seppälä
+
+    Permission is hereby granted, free of charge, to any person obtaining a copy
+    of this software and associated documentation files (the "Software"), to deal
+    in the Software without restriction, including without limitation the rights
+    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+    copies of the Software, and to permit persons to whom the Software is
+    furnished to do so, subject to the following conditions:
+
+    The above copyright notice and this permission notice shall be included in
+    all copies or substantial portions of the Software.
+
+    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+    THE SOFTWARE.
+
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <groupId>com.iluwatar</groupId>
+        <artifactId>java-design-patterns</artifactId>
+        <version>1.26.0-SNAPSHOT</version>
+    </parent>
+
+    <artifactId>fallback</artifactId>
+
+    <properties>
+        <maven.compiler.source>17</maven.compiler.source>
+        <maven.compiler.target>17</maven.compiler.target>
+        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+    </properties>
+    <dependencies>
+    <dependency>
+        <groupId>org.junit.jupiter</groupId>
+        <artifactId>junit-jupiter-engine</artifactId>
+        <version>5.8.2</version>
+        <scope>test</scope>
+    </dependency>
+    <dependency>
+        <groupId>org.junit.jupiter</groupId>
+        <artifactId>junit-jupiter-api</artifactId>
+        <version>5.8.2</version>
+        <scope>test</scope>
+    </dependency>
+            <dependency>
+                <groupId>org.junit.jupiter</groupId>
+                <artifactId>junit-jupiter</artifactId>
+                <version>5.8.2</version>
+                <scope>test</scope>
+            </dependency>
+            <dependency>
+                <groupId>org.mockito</groupId>
+                <artifactId>mockito-core</artifactId>
+                <version>4.5.1</version>
+                <scope>test</scope>
+            </dependency>
+        
+        </dependencies>
+</project>
\ No newline at end of file
diff --git a/fallback/src/main/java/com/iluwatar/fallback/App.java b/fallback/src/main/java/com/iluwatar/fallback/App.java
new file mode 100644
index 000000000000..75a08cd54700
--- /dev/null
+++ b/fallback/src/main/java/com/iluwatar/fallback/App.java
@@ -0,0 +1,177 @@
+package com.iluwatar.fallback;
+
+import java.net.http.HttpClient;
+import java.time.Duration;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Demonstrates the Fallback pattern with Circuit Breaker implementation.
+ * 
+ * <p>This application shows how to:
+ * - Handle failures gracefully using fallback mechanisms.
+ * - Implement circuit breaker pattern to prevent cascade failures.
+ * - Configure timeouts and retries for resilient service calls.
+ * - Monitor service health and performance.
+ * 
+ * <p>The app uses a primary remote service with a local cache fallback.
+ */
+public class App {
+  private static final Logger LOGGER = LoggerFactory.getLogger(App.class);
+  
+  /** Service call timeout in seconds. */
+  private static final int TIMEOUT = 2;
+  
+  /** Maximum number of retry attempts. */
+  private static final int MAX_ATTEMPTS = 3;
+  
+  /** Delay between retry attempts in milliseconds. */
+  private static final int RETRY_DELAY = 1000;
+  
+  /** Default API endpoint for remote service. */
+  private static final String DEFAULT_API_URL = "https://jsonplaceholder.typicode.com/todos";
+
+  /** Service execution state tracking. */
+  private enum ExecutionState {
+    READY, RUNNING, FAILED, SHUTDOWN
+  }
+
+  private final CircuitBreaker circuitBreaker;
+  private final ExecutorService executor;
+  private final Service primaryService;
+  private final Service fallbackService;
+  private volatile ExecutionState state;
+
+  /**
+   * Constructs an App with default configuration.
+   * Creates HTTP client with timeout, remote service, and local cache fallback.
+   */
+  public App() {
+    HttpClient httpClient = createHttpClient();
+    this.primaryService = new RemoteService(DEFAULT_API_URL, httpClient);
+    this.fallbackService = new LocalCacheService();
+    this.circuitBreaker = new DefaultCircuitBreaker(MAX_ATTEMPTS);
+    this.executor = Executors.newSingleThreadExecutor();
+    this.state = ExecutionState.READY;
+  }
+
+  private HttpClient createHttpClient() {
+    try {
+      return HttpClient.newBuilder()
+          .connectTimeout(Duration.ofSeconds(TIMEOUT))
+          .build();
+    } catch (Exception e) {
+      LOGGER.warn("Failed to create custom HTTP client, using default", e);
+      return HttpClient.newHttpClient();
+    }
+  }
+
+  /**
+   * Constructs an App with custom services and circuit breaker.
+   *
+   * @param primaryService Primary service implementation
+   * @param fallbackService Fallback service implementation
+   * @param circuitBreaker Circuit breaker implementation
+   * @throws IllegalArgumentException if any parameter is null
+   */
+  public App(Service primaryService, Service fallbackService, CircuitBreaker circuitBreaker) {
+    if (primaryService == null || fallbackService == null || circuitBreaker == null) {
+      throw new IllegalArgumentException("All services must be non-null");
+    }
+    this.circuitBreaker = circuitBreaker;
+    this.executor = Executors.newSingleThreadExecutor();
+    this.primaryService = primaryService;
+    this.fallbackService = fallbackService;
+    this.state = ExecutionState.READY;
+  }
+
+  /**
+   * Executes the service with fallback mechanism.
+   *
+   * @return Result from primary or fallback service
+   * @throws IllegalStateException if app is shutdown
+   */
+  public String executeWithFallback() {
+    if (state == ExecutionState.SHUTDOWN) {
+      throw new IllegalStateException("Application is shutdown");
+    }
+
+    state = ExecutionState.RUNNING;
+    if (circuitBreaker.isOpen()) {
+      LOGGER.info("Circuit breaker is open, using cached data");
+      return getFallbackData();
+    }
+
+    try {
+      Future<String> future = executor.submit(primaryService::getData);
+      String result = future.get(TIMEOUT, TimeUnit.SECONDS);
+      circuitBreaker.recordSuccess();
+      updateFallbackCache(result);
+      return result;
+    } catch (Exception e) {
+      LOGGER.warn("Primary service failed: {}", e.getMessage());
+      circuitBreaker.recordFailure();
+      state = ExecutionState.FAILED;
+      return getFallbackData();
+    }
+  }
+
+  private String getFallbackData() {
+    try {
+      return fallbackService.getData();
+    } catch (Exception e) {
+      LOGGER.error("Fallback service failed: {}", e.getMessage());
+      return "System is currently unavailable";
+    }
+  }
+
+  private void updateFallbackCache(String result) {
+    if (fallbackService instanceof LocalCacheService) {
+      ((LocalCacheService) fallbackService).updateCache("default", result);
+    }
+  }
+
+  /**
+   * Shuts down the executor service and cleans up resources.
+   */
+  public void shutdown() {
+    state = ExecutionState.SHUTDOWN;
+    executor.shutdown();
+    try {
+      if (!executor.awaitTermination(5, TimeUnit.SECONDS)) {
+        executor.shutdownNow();
+      }
+    } catch (InterruptedException e) {
+      executor.shutdownNow();
+      Thread.currentThread().interrupt();
+      LOGGER.error("Shutdown interrupted", e);
+    }
+  }
+
+  /**
+   * Main method demonstrating the fallback pattern.
+   */
+  public static void main(String[] args) {
+    App app = new App();
+    try {
+      for (int i = 0; i < MAX_ATTEMPTS; i++) {
+        try {
+          String result = app.executeWithFallback();
+          LOGGER.info("Attempt {}: Result = {}", i + 1, result);
+        } catch (Exception e) {
+          LOGGER.error("Attempt {} failed: {}", i + 1, e.getMessage());
+        }
+        Thread.sleep(RETRY_DELAY);
+      }
+    } catch (InterruptedException e) {
+      Thread.currentThread().interrupt();
+      LOGGER.error("Main thread interrupted", e);
+    } finally {
+      app.shutdown();
+    }
+  }
+}
diff --git a/fallback/src/main/java/com/iluwatar/fallback/CircuitBreaker.java b/fallback/src/main/java/com/iluwatar/fallback/CircuitBreaker.java
new file mode 100644
index 000000000000..df114d8f51be
--- /dev/null
+++ b/fallback/src/main/java/com/iluwatar/fallback/CircuitBreaker.java
@@ -0,0 +1,48 @@
+/*
+ * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).
+ *
+ * The MIT License
+ * Copyright © 2014-2022 Ilkka Seppälä
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+package com.iluwatar.fallback;
+
+/**
+ * Interface defining the contract for a circuit breaker implementation.
+ * Provides methods to check circuit state and record success/failure events.
+ */
+public interface CircuitBreaker {
+  boolean isOpen();
+  boolean allowRequest();
+  void recordSuccess();
+  void recordFailure();
+  CircuitState getState();
+  void reset();
+
+  /**
+   * Represents the possible states of the circuit breaker.
+   * CLOSED - Circuit is closed and allowing requests
+   * HALF_OPEN - Circuit is testing if service has recovered
+   * OPEN - Circuit is open and blocking requests
+   */
+  enum CircuitState {
+    CLOSED, HALF_OPEN, OPEN
+  }
+}
\ No newline at end of file
diff --git a/fallback/src/main/java/com/iluwatar/fallback/DefaultCircuitBreaker.java b/fallback/src/main/java/com/iluwatar/fallback/DefaultCircuitBreaker.java
new file mode 100644
index 000000000000..a8a857ffaca4
--- /dev/null
+++ b/fallback/src/main/java/com/iluwatar/fallback/DefaultCircuitBreaker.java
@@ -0,0 +1,182 @@
+/*
+ * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).
+ *
+ * The MIT License
+ * Copyright © 2014-2022 Ilkka Seppälä
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+package com.iluwatar.fallback;
+
+import java.time.Duration;
+import java.time.Instant;
+import java.util.Queue;
+import java.util.concurrent.ConcurrentLinkedQueue;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Circuit breaker implementation with three states:
+ * - CLOSED: Normal operation, requests flow through
+ * - OPEN: Failing fast, no attempts to call primary service
+ * - HALF_OPEN: Testing if service has recovered.
+ *
+ * <p>Features:
+ * - Thread-safe operation
+ * - Sliding window failure counting
+ * - Automatic state transitions
+ * - Configurable thresholds and timeouts
+ * - Recovery validation period
+ */
+public class DefaultCircuitBreaker implements CircuitBreaker {
+  private static final Logger LOGGER = LoggerFactory.getLogger(DefaultCircuitBreaker.class);
+  
+  // Circuit breaker configuration
+  private static final long RESET_TIMEOUT = 5000; // 5 seconds
+  private static final Duration MIN_HALF_OPEN_DURATION = Duration.ofSeconds(30);
+
+  private volatile State state;
+  private final int failureThreshold;
+  private volatile long lastFailureTime;
+  private final Queue<Long> failureTimestamps;
+  private final Duration windowSize;
+  private volatile Instant halfOpenStartTime;
+
+  /**
+   * Constructs a DefaultCircuitBreaker with the given failure threshold.
+   *
+   * @param failureThreshold the number of failures to trigger the circuit breaker
+   */
+  public DefaultCircuitBreaker(final int failureThreshold) {
+    this.failureThreshold = failureThreshold;
+    this.state = State.CLOSED;
+    this.failureTimestamps = new ConcurrentLinkedQueue<>();
+    this.windowSize = Duration.ofMinutes(1);
+  }
+
+  /**
+   * Checks if a request should be allowed through the circuit breaker.
+   * @return true if request should be allowed, false if it should be blocked
+   */
+  @Override
+  public synchronized boolean allowRequest() {
+    if (state == State.CLOSED) {
+      return true;
+    }
+    if (state == State.OPEN) {
+      if (System.currentTimeMillis() - lastFailureTime > RESET_TIMEOUT) {
+        transitionToHalfOpen();
+        return true;
+      }
+      return false;
+    }
+    // In HALF_OPEN state, allow limited testing
+    return true;
+  }
+
+  @Override
+  public synchronized boolean isOpen() {
+    if (state == State.OPEN) {
+      if (System.currentTimeMillis() - lastFailureTime > RESET_TIMEOUT) {
+        transitionToHalfOpen();
+        return false;
+      }
+      return true;
+    }
+    return false;
+  }
+
+  /**
+   * Transitions circuit breaker to half-open state.
+   * Clears failure history and starts recovery monitoring.
+   */
+  private synchronized void transitionToHalfOpen() {
+    state = State.HALF_OPEN;
+    halfOpenStartTime = Instant.now();
+    failureTimestamps.clear();
+    LOGGER.info("Circuit breaker transitioning to HALF_OPEN state");
+  }
+
+  /**
+   * Records successful operation.
+   * In half-open state, requires sustained success before closing circuit.
+   */
+  @Override
+  public synchronized void recordSuccess() {
+    if (state == State.HALF_OPEN) {
+      if (Duration.between(halfOpenStartTime, Instant.now())
+          .compareTo(MIN_HALF_OPEN_DURATION) >= 0) {
+        LOGGER.info("Circuit breaker recovering - transitioning to CLOSED");
+        state = State.CLOSED;
+      }
+    }
+    failureTimestamps.clear();
+  }
+
+  @Override
+  public synchronized void recordFailure() {
+    long now = System.currentTimeMillis();
+    failureTimestamps.offer(now);
+
+    // Cleanup old timestamps outside window
+    while (!failureTimestamps.isEmpty() 
+        && failureTimestamps.peek() < now - windowSize.toMillis()) {
+      failureTimestamps.poll();
+    }
+
+    if (failureTimestamps.size() >= failureThreshold) {
+      LOGGER.warn("Failure threshold reached - opening circuit breaker");
+      state = State.OPEN;
+      lastFailureTime = now;
+    }
+  }
+
+  @Override
+  public void reset() {
+    failureTimestamps.clear();
+    lastFailureTime = 0;
+    state = State.CLOSED;
+  }
+
+  /**
+   * Returns the current state of the circuit breaker mapped to the public enum.
+   * @return Current CircuitState value
+   */
+  @Override
+  public synchronized CircuitState getState() {
+    if (state == State.OPEN && System.currentTimeMillis() - lastFailureTime > RESET_TIMEOUT) {
+      transitionToHalfOpen();
+    }
+    return switch (state) {
+      case CLOSED -> CircuitState.CLOSED;
+      case OPEN -> CircuitState.OPEN;
+      case HALF_OPEN -> CircuitState.HALF_OPEN;
+    };
+  }
+
+  /**
+   * Internal states of the circuit breaker.
+   * Maps to the public CircuitState enum for external reporting.
+   */
+  private enum State {
+    CLOSED,
+    OPEN,
+    HALF_OPEN
+  }
+}
\ No newline at end of file
diff --git a/fallback/src/main/java/com/iluwatar/fallback/FallbackService.java b/fallback/src/main/java/com/iluwatar/fallback/FallbackService.java
new file mode 100644
index 000000000000..e4a1b847aee0
--- /dev/null
+++ b/fallback/src/main/java/com/iluwatar/fallback/FallbackService.java
@@ -0,0 +1,307 @@
+/*
+ * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).
+ *
+ * The MIT License
+ * Copyright © 2014-2022 Ilkka Seppälä
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+package com.iluwatar.fallback;
+
+import java.time.Duration;
+import java.time.Instant;
+import java.util.Queue;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ConcurrentLinkedQueue;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.ThreadLocalRandom;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * FallbackService implements a resilient service pattern with circuit breaking,
+ * rate limiting, and fallback capabilities. It manages service degradation gracefully
+ * by monitoring service health and automatically switching to fallback mechanisms
+ * when the primary service is unavailable or performing poorly.
+ *
+ * <p>Features:
+ * - Circuit breaking to prevent cascading failures.
+ * - Rate limiting to protect from overload.
+ * - Automatic fallback to backup service.
+ * - Health monitoring and metrics collection.
+ * - Retry mechanism with exponential backoff.
+ */
+public class FallbackService implements Service, AutoCloseable {
+  
+  /** Logger for this class. */
+  private static final Logger LOGGER = LoggerFactory.getLogger(FallbackService.class);
+  
+  /** Timeout in seconds for primary service calls. */
+  private static final int TIMEOUT = 2;
+  
+  /** Maximum number of retry attempts for failed requests. */
+  private static final int MAX_RETRIES = 3;
+  
+  /** Base delay between retries in milliseconds. */
+  private static final long RETRY_DELAY_MS = 1000;
+  
+  /** Minimum success rate threshold before triggering warnings. */
+  private static final double MIN_SUCCESS_RATE = 0.6;
+  
+  /** Maximum requests allowed per minute for rate limiting. */
+  private static final int MAX_REQUESTS_PER_MINUTE = 60;
+
+  /** Service state tracking. */
+  private enum ServiceState {
+    STARTING, RUNNING, DEGRADED, CLOSED
+  }
+
+  private volatile ServiceState state = ServiceState.STARTING;
+  
+  private final CircuitBreaker circuitBreaker;
+  private final ExecutorService executor;
+  private final Service primaryService;
+  private final Service fallbackService;
+  private final ServiceMonitor monitor;
+  private final ScheduledExecutorService healthChecker;
+  private final RateLimiter rateLimiter;
+
+  /**
+   * Constructs a new FallbackService with the specified components.
+   *
+   * @param primaryService Main service implementation
+   * @param fallbackService Backup service for failover
+   * @param circuitBreaker Circuit breaker for failure detection
+   * @throws IllegalArgumentException if any parameter is null
+   */
+  public FallbackService(Service primaryService, Service fallbackService, CircuitBreaker circuitBreaker) {
+    // Validate parameters
+    if (primaryService == null || fallbackService == null || circuitBreaker == null) {
+      throw new IllegalArgumentException("All service components must be non-null");
+    }
+
+    // Initialize components
+    this.primaryService = primaryService;
+    this.fallbackService = fallbackService;
+    this.circuitBreaker = circuitBreaker;
+    this.executor = Executors.newCachedThreadPool();
+    this.monitor = new ServiceMonitor();
+    this.healthChecker = Executors.newSingleThreadScheduledExecutor();
+    this.rateLimiter = new RateLimiter(MAX_REQUESTS_PER_MINUTE, Duration.ofMinutes(1));
+    
+    startHealthChecker();
+    state = ServiceState.RUNNING;
+  }
+
+  /**
+   * Starts the health monitoring schedule.
+   * Monitors service health metrics and logs warnings when thresholds are exceeded.
+   */
+  private void startHealthChecker() {
+    healthChecker.scheduleAtFixedRate(() -> {
+      try {
+        if (monitor.getSuccessRate() < MIN_SUCCESS_RATE) {
+          LOGGER.warn("Success rate below threshold: {}", monitor.getSuccessRate());
+        }
+        if (Duration.between(monitor.getLastSuccessTime(), Instant.now()).toMinutes() > 5) {
+          LOGGER.warn("No successful requests in last 5 minutes");
+        }
+      } catch (Exception e) {
+        LOGGER.error("Health check failed: {}", e.getMessage());
+      }
+    }, 1, 1, TimeUnit.MINUTES);
+  }
+
+  /**
+   * Retrieves data from the primary service with a fallback mechanism.
+   *
+   * @return the data from the primary or fallback service
+   * @throws Exception if an error occurs while retrieving the data
+   */
+  @Override
+  public String getData() throws Exception {
+    // Validate service state
+    if (state == ServiceState.CLOSED) {
+      throw new ServiceException("Service is closed");
+    }
+
+    // Apply rate limiting
+    if (!rateLimiter.tryAcquire()) {
+      state = ServiceState.DEGRADED;
+      LOGGER.warn("Rate limit exceeded, switching to fallback");
+      monitor.recordFallback();
+      return executeFallback();
+    }
+
+    // Check circuit breaker
+    if (!circuitBreaker.allowRequest()) {
+      state = ServiceState.DEGRADED;
+      LOGGER.warn("Circuit breaker open, switching to fallback");
+      monitor.recordFallback();
+      return executeFallback();
+    }
+
+    Instant start = Instant.now();
+    Exception lastException = null;
+
+    for (int attempt = 0; attempt < MAX_RETRIES; attempt++) {
+      try {
+        if (attempt > 0) {
+          // Exponential backoff with jitter
+          long delay = RETRY_DELAY_MS * (long) Math.pow(2, attempt - 1);
+          delay += ThreadLocalRandom.current().nextLong(delay / 2);
+          Thread.sleep(delay);
+        }
+
+        String result = executeWithTimeout(primaryService::getData);
+        Duration responseTime = Duration.between(start, Instant.now());
+        
+        circuitBreaker.recordSuccess();
+        monitor.recordSuccess(responseTime);
+        updateFallbackCache(result);
+        
+        return result;
+      } catch (Exception e) {
+        lastException = e;
+        LOGGER.warn("Attempt {} failed: {}", attempt + 1, e.getMessage());
+        
+        // Don't retry certain exceptions
+        if (e instanceof ServiceException 
+            || e instanceof IllegalArgumentException) {
+          break;
+        }
+
+        circuitBreaker.recordFailure();
+        monitor.recordError();
+      }
+    }
+    
+    monitor.recordFallback();
+    if (lastException != null) {
+      LOGGER.error("All attempts failed. Last error: {}", lastException.getMessage());
+    }
+    return executeFallback();
+  }
+
+  /**
+   * Executes a service call with timeout protection.
+   * @param task The service call to execute
+   * @return The service response
+   * @throws Exception if the call fails or times out
+   */
+  private String executeWithTimeout(Callable<String> task) throws Exception {
+    Future<String> future = executor.submit(task);
+    try {
+      return future.get(TIMEOUT, TimeUnit.SECONDS);
+    } catch (TimeoutException e) {
+      future.cancel(true);
+      throw new ServiceException("Service timeout after " + TIMEOUT + " seconds", e);
+    }
+  }
+
+  private String executeFallback() {
+    try {
+      return fallbackService.getData();
+    } catch (Exception e) {
+      LOGGER.error("Fallback service failed: {}", e.getMessage());
+      return "Service temporarily unavailable";
+    }
+  }
+
+  private void updateFallbackCache(String result) {
+    try {
+      if (fallbackService instanceof LocalCacheService) {
+        ((LocalCacheService) fallbackService).updateCache("default", result);
+      }
+    } catch (Exception e) {
+      LOGGER.warn("Failed to update fallback cache: {}", e.getMessage());
+    }
+  }
+
+  /**
+   * Shuts down the executor service.
+   */
+  @Override
+  public void close() throws Exception {
+    state = ServiceState.CLOSED;
+    executor.shutdown();
+    healthChecker.shutdown();
+    try {
+      if (!executor.awaitTermination(5, TimeUnit.SECONDS)) {
+        executor.shutdownNow();
+      }
+      if (!healthChecker.awaitTermination(5, TimeUnit.SECONDS)) {
+        healthChecker.shutdownNow();
+      }
+    } catch (InterruptedException e) {
+      executor.shutdownNow();
+      healthChecker.shutdownNow();
+      Thread.currentThread().interrupt();
+      throw new Exception("Failed to shutdown executors", e);
+    }
+  }
+  
+  public ServiceMonitor getMonitor() {
+    return monitor;
+  }
+
+  /**
+   * Returns the current service state.
+   * @return Current ServiceState enum value
+   */
+  public ServiceState getState() {
+    return state;
+  }
+
+  /**
+   * Rate limiter implementation using a sliding window approach.
+   * Manages request rate by tracking timestamps within a rolling time window.
+   */
+  private static class RateLimiter {
+    private final int maxRequests;
+    private final Duration window;
+    private final Queue<Long> requestTimestamps = new ConcurrentLinkedQueue<>();
+
+    RateLimiter(int maxRequests, Duration window) {
+      this.maxRequests = maxRequests;
+      this.window = window;
+    }
+
+    boolean tryAcquire() {
+      long now = System.currentTimeMillis();
+      long windowStart = now - window.toMillis();
+      
+      // Removing expired timestamps
+      while (!requestTimestamps.isEmpty() && requestTimestamps.peek() < windowStart) {
+        requestTimestamps.poll();
+      }
+      
+      if (requestTimestamps.size() < maxRequests) {
+        requestTimestamps.offer(now);
+        return true;
+      }
+      return false;
+    }
+  }
+}
\ No newline at end of file
diff --git a/fallback/src/main/java/com/iluwatar/fallback/LocalCacheService.java b/fallback/src/main/java/com/iluwatar/fallback/LocalCacheService.java
new file mode 100644
index 000000000000..8a1af9b10269
--- /dev/null
+++ b/fallback/src/main/java/com/iluwatar/fallback/LocalCacheService.java
@@ -0,0 +1,198 @@
+/*
+ * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).
+ *
+ * The MIT License
+ * Copyright © 2014-2022 Ilkka Seppälä
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+package com.iluwatar.fallback;
+
+import ch.qos.logback.classic.Logger;
+import java.time.Duration;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.TimeUnit;
+import org.slf4j.LoggerFactory;
+
+/**
+ * LocalCacheService implementation that provides cached data with fallback mechanism.
+ * This service maintains a local cache with multiple fallback levels and automatic
+ * expiration of cached entries. If the primary data source fails, the service
+ * falls back to cached data in order of priority.
+ */
+public class LocalCacheService implements Service, AutoCloseable {
+  
+  /** Cache instance for storing key-value pairs. */
+  private final Cache<String, String> cache;
+  
+  /** Default cache entry expiration time in milliseconds. */
+  private static final long CACHE_EXPIRY_MS = 300000;
+  
+  /** Logger instance for this class. */
+  private static final Logger LOGGER = (Logger) LoggerFactory.getLogger(LocalCacheService.class);
+  
+  /** Interval for periodic cache refresh operations. */
+  private static final Duration CACHE_REFRESH_INTERVAL = Duration.ofMinutes(5);
+  
+  /** Executor service for scheduling cache maintenance tasks. */
+  private final ScheduledExecutorService refreshExecutor;
+
+  /**
+   * Defines the fallback chain priority levels.
+   * Entries are tried in order from PRIMARY to TERTIARY until valid data is found.
+   */
+  private enum FallbackLevel {
+    PRIMARY("default"),
+    SECONDARY("backup1"),
+    TERTIARY("backup2");
+
+    private final String key;
+    
+    FallbackLevel(String key) {
+      this.key = key;
+    }
+  }
+
+  /**
+   * Constructs a new LocalCacheService with initialized cache and scheduled maintenance.
+   */
+  public LocalCacheService() {
+    this.cache = new Cache<>(CACHE_EXPIRY_MS);
+    this.refreshExecutor = Executors.newSingleThreadScheduledExecutor();
+    initializeDefaultCache();
+    scheduleMaintenanceTasks();
+  }
+
+  /**
+   * Initializes the cache with default fallback values.
+   */
+  private void initializeDefaultCache() {
+    cache.put(FallbackLevel.PRIMARY.key, "Default fallback response");
+    cache.put(FallbackLevel.SECONDARY.key, "Secondary fallback response");
+    cache.put(FallbackLevel.TERTIARY.key, "Tertiary fallback response");
+  }
+
+  /**
+   * Schedules periodic cache maintenance tasks.
+   */
+  private void scheduleMaintenanceTasks() {
+    refreshExecutor.scheduleAtFixedRate(
+        this::cleanupExpiredEntries,
+        CACHE_REFRESH_INTERVAL.toMinutes(),
+        CACHE_REFRESH_INTERVAL.toMinutes(),
+        TimeUnit.MINUTES
+    );
+  }
+
+  /**
+   * Removes expired entries from the cache.
+   */
+  private void cleanupExpiredEntries() {
+    try {
+      cache.cleanup();
+      LOGGER.debug("Completed cache cleanup");
+    } catch (Exception e) {
+      LOGGER.error("Error during cache cleanup", e);
+    }
+  }
+
+  @Override
+  public void close() throws Exception {
+    if (refreshExecutor != null) {
+      refreshExecutor.shutdown();
+      try {
+        if (!refreshExecutor.awaitTermination(5, TimeUnit.SECONDS)) {
+          refreshExecutor.shutdownNow();
+        }
+      } catch (InterruptedException e) {
+        refreshExecutor.shutdownNow();
+        Thread.currentThread().interrupt();
+        throw new Exception("Failed to shutdown refresh executor", e);
+      }
+    }
+  }
+
+  /**
+   * Retrieves data using the fallback chain mechanism.
+   * @return The cached data from the highest priority available fallback level.
+   * @throws Exception if no valid data is available at any fallback level.
+   */
+  @Override
+  public String getData() throws Exception {
+    // Try each fallback level in order of priority
+    for (FallbackLevel level : FallbackLevel.values()) {
+      String value = cache.get(level.key);
+      if (value != null) {
+        LOGGER.debug("Retrieved value from {} fallback level", level);
+        return value;
+      }
+      LOGGER.debug("Cache miss at {} fallback level", level);
+    }
+    throw new Exception("All fallback levels exhausted");
+  }
+
+  /**
+   * Updates the cached data for a specific key.
+   * @param key The cache key to update.
+   * @param value The new value to cache.
+   */
+  public void updateCache(String key, String value) {
+    cache.put(key, value);
+  }
+
+  /**
+   * Thread-safe cache implementation with entry expiration.
+   */
+  private static class Cache<K, V> {
+    private final ConcurrentHashMap<K, CacheEntry<V>> map;
+    private final long expiryMs;
+    
+    Cache(long expiryMs) {
+      this.map = new ConcurrentHashMap<>();
+      this.expiryMs = expiryMs;
+    }
+    
+    V get(K key) {
+      CacheEntry<V> entry = map.get(key);
+      if (entry != null && !entry.isExpired()) {
+        return entry.value;
+      }
+      return null;
+    }
+    
+    void put(K key, V value) {
+      map.put(key, new CacheEntry<>(value, System.currentTimeMillis() + expiryMs));
+    }
+
+    /**
+     * Removes all expired entries from the cache.
+     */
+    void cleanup() {
+      map.entrySet().removeIf(entry -> entry.getValue().isExpired());
+    }
+
+    private record CacheEntry<V>(V value, long expiryTime) {
+      boolean isExpired() {
+        return System.currentTimeMillis() > expiryTime;
+      }
+    }
+  }
+}
\ No newline at end of file
diff --git a/fallback/src/main/java/com/iluwatar/fallback/RemoteService.java b/fallback/src/main/java/com/iluwatar/fallback/RemoteService.java
new file mode 100644
index 000000000000..1902b6c629dd
--- /dev/null
+++ b/fallback/src/main/java/com/iluwatar/fallback/RemoteService.java
@@ -0,0 +1,63 @@
+/*
+ * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).
+ *
+ * The MIT License
+ * Copyright © 2014-2022 Ilkka Seppälä
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+package com.iluwatar.fallback;
+
+import java.net.URI;
+import java.net.http.HttpClient;
+import java.net.http.HttpRequest;
+import java.net.http.HttpResponse;
+import java.time.Duration;
+
+/**
+ * RemoteService implementation that makes HTTP calls to an external API.
+ * This service acts as the primary service in the fallback pattern.
+ */
+public class RemoteService implements Service {
+  private final String apiUrl;
+  private final HttpClient httpClient;
+  private static final int TIMEOUT_SECONDS = 2;
+
+  public RemoteService(String apiUrl, HttpClient httpClient) {
+    this.apiUrl = apiUrl;
+    this.httpClient = httpClient;
+  }
+
+  @Override
+  public String getData() throws Exception {
+    HttpRequest request = HttpRequest.newBuilder()
+        .uri(URI.create(apiUrl))
+        .timeout(Duration.ofSeconds(TIMEOUT_SECONDS))
+        .GET()
+        .build();
+
+    HttpResponse<String> response = httpClient.send(request, HttpResponse.BodyHandlers.ofString());
+    
+    if (response.statusCode() != 200) {
+      throw new Exception("Remote service failed with status code: " + response.statusCode());
+    }
+    
+    return response.body();
+  }
+}
diff --git a/fallback/src/main/java/com/iluwatar/fallback/Service.java b/fallback/src/main/java/com/iluwatar/fallback/Service.java
new file mode 100644
index 000000000000..2c5cbba22c8b
--- /dev/null
+++ b/fallback/src/main/java/com/iluwatar/fallback/Service.java
@@ -0,0 +1,38 @@
+/*
+ * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).
+ *
+ * The MIT License
+ * Copyright © 2014-2022 Ilkka Seppälä
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+package com.iluwatar.fallback;
+
+/**
+ * Service interface that defines a method to retrieve data.
+ */
+public interface Service {
+  /**
+   * Retrieves data.
+   *
+   * @return the data
+   * @throws Exception if an error occurs while retrieving the data
+   */
+  String getData() throws Exception;
+}
\ No newline at end of file
diff --git a/fallback/src/main/java/com/iluwatar/fallback/ServiceException.java b/fallback/src/main/java/com/iluwatar/fallback/ServiceException.java
new file mode 100644
index 000000000000..dcc4638dae80
--- /dev/null
+++ b/fallback/src/main/java/com/iluwatar/fallback/ServiceException.java
@@ -0,0 +1,33 @@
+package com.iluwatar.fallback;
+
+import java.io.Serial;
+
+/**
+ * Custom exception class for service-related errors in the fallback pattern.
+ * This exception is thrown when a service operation fails and needs to be handled
+ * by the fallback mechanism.
+ */
+public class ServiceException extends Exception {
+  
+  @Serial
+  private static final long serialVersionUID = 1L;
+
+  /**
+   * Constructs a new ServiceException with the specified detail message.
+   *
+   * @param message the detail message describing the error
+   */
+  public ServiceException(String message) {
+    super(message);
+  }
+
+  /**
+   * Constructs a new ServiceException with the specified detail message and cause.
+   *
+   * @param message the detail message describing the error
+   * @param cause the cause of the exception
+   */
+  public ServiceException(String message, Throwable cause) {
+    super(message, cause);
+  }
+}
diff --git a/fallback/src/main/java/com/iluwatar/fallback/ServiceMonitor.java b/fallback/src/main/java/com/iluwatar/fallback/ServiceMonitor.java
new file mode 100644
index 000000000000..82e67d91dd22
--- /dev/null
+++ b/fallback/src/main/java/com/iluwatar/fallback/ServiceMonitor.java
@@ -0,0 +1,180 @@
+package com.iluwatar.fallback;
+
+import java.time.Duration;
+import java.time.Instant;
+import java.util.Queue;
+import java.util.concurrent.ConcurrentLinkedQueue;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.concurrent.atomic.AtomicReference;
+
+/**
+ * ServiceMonitor class provides monitoring capabilities for tracking service performance metrics.
+ * It maintains thread-safe counters for success, fallback, and error rates, as well as timing information.
+ */
+public class ServiceMonitor {
+  private final AtomicInteger successCount = new AtomicInteger(0);
+  private final AtomicInteger fallbackCount = new AtomicInteger(0);
+  private final AtomicInteger errorCount = new AtomicInteger(0);
+  private final AtomicReference<Instant> lastSuccessTime = new AtomicReference<>(Instant.now());
+  private final AtomicReference<Instant> lastFailureTime = new AtomicReference<>(Instant.now());
+  private final AtomicReference<Duration> lastResponseTime = new AtomicReference<>(Duration.ZERO);
+  
+  // Sliding window for metrics
+  private final Queue<ServiceMetric> metrics = new ConcurrentLinkedQueue<>();
+  
+  private record ServiceMetric(Instant timestamp, MetricType type, Duration responseTime) {}
+  private enum MetricType { SUCCESS, FALLBACK, ERROR }
+
+  /**
+   * Weight applied to fallback operations when calculating success rate.
+   * Values between 0.0 and 1.0:
+   * - 1.0 means fallbacks count as full successes
+   * - 0.0 means fallbacks count as failures
+   * - Default 0.7 indicates fallbacks are "partial successes" since they provide
+   *   degraded but still functional service to users
+   */
+  private final double fallbackWeight;
+
+  /**
+   * Duration for which metrics should be retained.
+   * Metrics older than this window will be removed during pruning.
+   */
+  private final Duration metricWindow;
+
+  /**
+   * Constructs a ServiceMonitor with default configuration.
+   * Uses default fallback weight of 0.7 and 5-minute metric window.
+   */
+  public ServiceMonitor() {
+    this(0.7, Duration.ofMinutes(5));
+  }
+
+  /**
+   * Constructs a ServiceMonitor with the specified fallback weight and metric window.
+   *
+   * @param fallbackWeight weight applied to fallback operations (0.0 to 1.0)
+   * @param metricWindow duration for which metrics should be retained
+   * @throws IllegalArgumentException if parameters are invalid
+   */
+  public ServiceMonitor(double fallbackWeight, Duration metricWindow) {
+    if (fallbackWeight < 0.0 || fallbackWeight > 1.0) {
+      throw new IllegalArgumentException("Fallback weight must be between 0.0 and 1.0");
+    }
+    if (metricWindow.isNegative() || metricWindow.isZero()) {
+      throw new IllegalArgumentException("Metric window must be positive");
+    }
+    this.fallbackWeight = fallbackWeight;
+    this.metricWindow = metricWindow;
+  }
+
+  /**
+   * Records a successful service operation with its response time.
+   *
+   * @param responseTime the duration of the successful operation
+   */
+  public void recordSuccess(Duration responseTime) {
+    successCount.incrementAndGet();
+    lastSuccessTime.set(Instant.now());
+    lastResponseTime.set(responseTime);
+    metrics.offer(new ServiceMetric(Instant.now(), MetricType.SUCCESS, responseTime));
+    pruneOldMetrics();
+  }
+  
+  /**
+   * Records a fallback operation in the monitoring metrics.
+   * This method increments the fallback counter and updates metrics.
+   * Fallbacks are considered as degraded successes.
+   */
+  public void recordFallback() {
+    fallbackCount.incrementAndGet();
+    Instant now = Instant.now();
+    Duration responseTime = lastResponseTime.get();
+    metrics.offer(new ServiceMetric(now, MetricType.FALLBACK, responseTime));
+    pruneOldMetrics();
+  }
+  
+  /**
+   * Records an error operation in the monitoring metrics.
+   * This method increments the error counter, updates the last failure time,
+   * and adds a new metric to the sliding window.
+   */
+  public void recordError() {
+    errorCount.incrementAndGet();
+    Instant now = Instant.now();
+    lastFailureTime.set(now);
+    Duration responseTime = lastResponseTime.get();
+    metrics.offer(new ServiceMetric(now, MetricType.ERROR, responseTime));
+    pruneOldMetrics();
+  }
+  
+  public int getSuccessCount() {
+    return successCount.get();
+  }
+  
+  public int getFallbackCount() {
+    return fallbackCount.get();
+  }
+  
+  public int getErrorCount() {
+    return errorCount.get();
+  }
+  
+  public Instant getLastSuccessTime() {
+    return lastSuccessTime.get();
+  }
+  
+  public Instant getLastFailureTime() {
+    return lastFailureTime.get();
+  }
+  
+  public Duration getLastResponseTime() {
+    return lastResponseTime.get();
+  }
+  
+  /**
+   * Calculates the success rate of service operations.
+   * The rate is calculated as successes / total attempts,
+   * where both fallbacks and errors count as failures.
+   *
+   * @return the success rate as a double between 0.0 and 1.0
+   */
+  public double getSuccessRate() {
+    int successes = successCount.get();
+    int fallbacks = fallbackCount.get();
+    int errors = errorCount.get();
+    int totalAttempts = successes + fallbacks + errors;
+    
+    if (totalAttempts == 0) {
+      return 0.0;
+    }
+    
+    // Weight fallbacks as partial successes since they provide degraded but functional service
+    return (successes + (fallbacks * fallbackWeight)) / totalAttempts;
+  }
+  
+  /**
+   * Resets all monitoring metrics to their initial values.
+   * This includes success count, error count, fallback count, and timing statistics.
+   */
+  public void reset() {
+    successCount.set(0);
+    fallbackCount.set(0);
+    errorCount.set(0);
+    lastSuccessTime.set(Instant.now());
+    lastFailureTime.set(Instant.now());
+    lastResponseTime.set(Duration.ZERO);
+    metrics.clear();
+  }
+  
+  /**
+   * Removes metrics that are older than the configured time window.
+   * This method is called automatically after each new metric is added
+   * to maintain a sliding window of recent metrics and prevent unbounded
+   * memory growth.
+   */
+  private void pruneOldMetrics() {
+    Instant cutoff = Instant.now().minus(metricWindow);
+    metrics.removeIf(metric -> metric.timestamp.isBefore(cutoff));
+  }
+}
+
diff --git a/fallback/src/test/java/com/iluwatar/fallback/DefaultCircuitBreakerTest.java b/fallback/src/test/java/com/iluwatar/fallback/DefaultCircuitBreakerTest.java
new file mode 100644
index 000000000000..4097daeee4ab
--- /dev/null
+++ b/fallback/src/test/java/com/iluwatar/fallback/DefaultCircuitBreakerTest.java
@@ -0,0 +1,290 @@
+package com.iluwatar.fallback;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Nested;
+import static org.junit.jupiter.api.Assertions.*;
+
+import java.util.ArrayList;
+import java.util.EnumSet;
+import java.util.List;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicInteger;
+
+/**
+ * Unit tests for {@link DefaultCircuitBreaker}.
+ * Tests state transitions and behaviors of the circuit breaker pattern implementation.
+ */
+class DefaultCircuitBreakerTest {
+    private DefaultCircuitBreaker circuitBreaker;
+    
+    private static final int FAILURE_THRESHOLD = 3;
+    private static final long RESET_TIMEOUT_MS = 5000;
+    private static final long WAIT_BUFFER = 100;
+
+    @BeforeEach
+    void setUp() {
+        circuitBreaker = new DefaultCircuitBreaker(FAILURE_THRESHOLD);
+    }
+
+    @Nested
+    @DisplayName("State Transition Tests")
+    class StateTransitionTests {
+        @Test
+        @DisplayName("Should start in CLOSED state")
+        void initialStateShouldBeClosed() {
+            assertEquals(CircuitBreaker.CircuitState.CLOSED, circuitBreaker.getState());
+            assertTrue(circuitBreaker.allowRequest());
+            assertFalse(circuitBreaker.isOpen());
+        }
+
+        @Test
+        @DisplayName("Should transition to OPEN after threshold failures")
+        void shouldTransitionToOpenAfterFailures() {
+            // When
+            for (int i = 0; i < FAILURE_THRESHOLD; i++) {
+                circuitBreaker.recordFailure();
+            }
+
+            // Then
+            assertEquals(CircuitBreaker.CircuitState.OPEN, circuitBreaker.getState());
+            assertFalse(circuitBreaker.allowRequest());
+            assertTrue(circuitBreaker.isOpen());
+        }
+
+        @Test
+        @DisplayName("Should transition to HALF-OPEN after timeout")
+        void shouldTransitionToHalfOpenAfterTimeout() throws InterruptedException {
+            // Given
+            for (int i = 0; i < FAILURE_THRESHOLD; i++) {
+                circuitBreaker.recordFailure();
+            }
+            assertTrue(circuitBreaker.isOpen());
+
+            // When
+            Thread.sleep(RESET_TIMEOUT_MS + WAIT_BUFFER);
+
+            // Then
+            assertEquals(CircuitBreaker.CircuitState.HALF_OPEN, circuitBreaker.getState());
+            assertTrue(circuitBreaker.allowRequest());
+            assertFalse(circuitBreaker.isOpen());
+        }
+    }
+
+    @Nested
+    @DisplayName("Behavior Tests")
+    class BehaviorTests {
+        @Test
+        @DisplayName("Success should reset failure count")
+        void successShouldResetFailureCount() {
+            // Given
+            circuitBreaker.recordFailure();
+            circuitBreaker.recordFailure();
+            
+            // When
+            circuitBreaker.recordSuccess();
+            
+            // Then
+            assertEquals(CircuitBreaker.CircuitState.CLOSED, circuitBreaker.getState());
+            assertTrue(circuitBreaker.allowRequest());
+            
+            // Additional verification
+            circuitBreaker.recordFailure();
+            assertFalse(circuitBreaker.isOpen());
+        }
+
+        @Test
+        @DisplayName("Reset should return to initial state")
+        void resetShouldReturnToInitialState() {
+            // Given
+            for (int i = 0; i < FAILURE_THRESHOLD; i++) {
+                circuitBreaker.recordFailure();
+            }
+            assertTrue(circuitBreaker.isOpen());
+
+            // When
+            circuitBreaker.reset();
+
+            // Then
+            assertEquals(CircuitBreaker.CircuitState.CLOSED, circuitBreaker.getState());
+            assertTrue(circuitBreaker.allowRequest());
+            assertFalse(circuitBreaker.isOpen());
+        }
+
+        @Test
+        @DisplayName("Should respect failure threshold boundary")
+        void shouldRespectFailureThresholdBoundary() {
+            // When/Then
+            for (int i = 0; i < FAILURE_THRESHOLD - 1; i++) {
+                circuitBreaker.recordFailure();
+                assertEquals(CircuitBreaker.CircuitState.CLOSED, circuitBreaker.getState());
+                assertFalse(circuitBreaker.isOpen());
+            }
+            
+            circuitBreaker.recordFailure();
+            assertEquals(CircuitBreaker.CircuitState.OPEN, circuitBreaker.getState());
+            assertTrue(circuitBreaker.isOpen());
+        }
+
+        @Test
+        @DisplayName("Should allow request in HALF-OPEN state")
+        void shouldAllowRequestInHalfOpenState() throws InterruptedException {
+            // Given
+            for (int i = 0; i < FAILURE_THRESHOLD; i++) {
+                circuitBreaker.recordFailure();
+            }
+            
+            // When
+            Thread.sleep(RESET_TIMEOUT_MS + WAIT_BUFFER);
+            
+            // Then
+            assertTrue(circuitBreaker.allowRequest());
+            assertEquals(CircuitBreaker.CircuitState.HALF_OPEN, circuitBreaker.getState());
+        }
+    }
+
+    @Nested
+    @DisplayName("Recovery Tests")
+    class RecoveryTests {
+        @Test
+        @DisplayName("Should close circuit after sustained success in half-open state")
+        void shouldCloseAfterSustainedSuccess() throws InterruptedException {
+            // Given
+            for (int i = 0; i < FAILURE_THRESHOLD; i++) {
+                circuitBreaker.recordFailure();
+            }
+            Thread.sleep(RESET_TIMEOUT_MS + WAIT_BUFFER);
+            assertEquals(CircuitBreaker.CircuitState.HALF_OPEN, circuitBreaker.getState());
+            
+            // When
+            Thread.sleep(30000); // Wait for MIN_HALF_OPEN_DURATION
+            circuitBreaker.recordSuccess();
+            
+            // Then
+            assertEquals(CircuitBreaker.CircuitState.CLOSED, circuitBreaker.getState());
+            assertTrue(circuitBreaker.allowRequest());
+        }
+
+        @Test
+        @DisplayName("Should remain half-open if success duration not met")
+        void shouldRemainHalfOpenBeforeSuccessDuration() throws InterruptedException {
+            // Given
+            for (int i = 0; i < FAILURE_THRESHOLD; i++) {
+                circuitBreaker.recordFailure();
+            }
+            Thread.sleep(RESET_TIMEOUT_MS + WAIT_BUFFER);
+            
+            // When
+            circuitBreaker.recordSuccess(); // Success before MIN_HALF_OPEN_DURATION
+            
+            // Then
+            assertEquals(CircuitBreaker.CircuitState.HALF_OPEN, circuitBreaker.getState());
+        }
+    }
+
+    @Nested
+    @DisplayName("Edge Case Tests")
+    class EdgeCaseTests {
+        @Test
+        @DisplayName("Should handle rapid state transitions")
+        void shouldHandleRapidStateTransitions() throws InterruptedException {
+            // Multiple rapid transitions
+            for (int i = 0; i < 3; i++) {
+                // To OPEN
+                for (int j = 0; j < FAILURE_THRESHOLD; j++) {
+                    circuitBreaker.recordFailure();
+                }
+                assertEquals(CircuitBreaker.CircuitState.OPEN, circuitBreaker.getState());
+                
+                // To HALF_OPEN
+                Thread.sleep(RESET_TIMEOUT_MS + WAIT_BUFFER);
+                assertTrue(circuitBreaker.allowRequest());
+                assertEquals(CircuitBreaker.CircuitState.HALF_OPEN, circuitBreaker.getState());
+                
+                // Back to CLOSED
+                circuitBreaker.reset();
+                assertEquals(CircuitBreaker.CircuitState.CLOSED, circuitBreaker.getState());
+            }
+        }
+
+        @Test
+        @DisplayName("Should handle boundary conditions for failure threshold")
+        void shouldHandleFailureThresholdBoundaries() {
+            // Given/When
+            for (int i = 0; i < FAILURE_THRESHOLD - 1; i++) {
+                circuitBreaker.recordFailure();
+                // Then - Should still be closed
+                assertEquals(CircuitBreaker.CircuitState.CLOSED, circuitBreaker.getState());
+            }
+            
+            // One more failure - Should open
+            circuitBreaker.recordFailure();
+            assertEquals(CircuitBreaker.CircuitState.OPEN, circuitBreaker.getState());
+            
+            // Additional failures should keep it open
+            circuitBreaker.recordFailure();
+            assertEquals(CircuitBreaker.CircuitState.OPEN, circuitBreaker.getState());
+        }
+    }
+
+    @Nested
+    @DisplayName("Concurrency Tests") 
+    class ConcurrencyTests {
+        private static final int THREAD_COUNT = 10;
+        private static final int OPERATIONS_PER_THREAD = 1000;
+
+        @Test
+        @DisplayName("Should handle concurrent state transitions safely")
+        void shouldHandleConcurrentTransitions() throws InterruptedException {
+            CountDownLatch startLatch = new CountDownLatch(1);
+            CountDownLatch endLatch = new CountDownLatch(THREAD_COUNT);
+            AtomicInteger errors = new AtomicInteger(0);
+            
+            // Create threads that will perform operations concurrently
+            List<Thread> threads = new ArrayList<>();
+            for (int i = 0; i < THREAD_COUNT; i++) {
+                Thread t = new Thread(() -> {
+                    try {
+                        startLatch.await(); // Wait for start signal
+                        for (int j = 0; j < OPERATIONS_PER_THREAD; j++) {
+                            try {
+                                if (j % 2 == 0) {
+                                    circuitBreaker.recordFailure();
+                                } else {
+                                    circuitBreaker.recordSuccess();
+                                }
+                                circuitBreaker.allowRequest();
+                                circuitBreaker.getState();
+                            } catch (Exception e) {
+                                errors.incrementAndGet();
+                            }
+                        }
+                    } catch (InterruptedException e) {
+                        Thread.currentThread().interrupt();
+                    } finally {
+                        endLatch.countDown();
+                    }
+                });
+                threads.add(t);
+                t.start();
+            }
+            
+            // Start all threads simultaneously
+            startLatch.countDown();
+            
+            // Wait for all threads to complete
+            assertTrue(endLatch.await(30, TimeUnit.SECONDS), 
+                "Concurrent operations should complete within timeout");
+            assertEquals(0, errors.get(), "Should handle concurrent operations without errors");
+            
+            // Verify circuit breaker is in a valid state
+            CircuitBreaker.CircuitState finalState = circuitBreaker.getState();
+            assertTrue(EnumSet.allOf(CircuitBreaker.CircuitState.class).contains(finalState),
+                "Circuit breaker should be in a valid state");
+        }
+    }
+}
diff --git a/fallback/src/test/java/com/iluwatar/fallback/FallbackServiceTest.java b/fallback/src/test/java/com/iluwatar/fallback/FallbackServiceTest.java
new file mode 100644
index 000000000000..74694f298574
--- /dev/null
+++ b/fallback/src/test/java/com/iluwatar/fallback/FallbackServiceTest.java
@@ -0,0 +1,217 @@
+package com.iluwatar.fallback;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Nested;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+
+import java.util.concurrent.*;
+import java.util.concurrent.atomic.AtomicInteger;
+import static org.junit.jupiter.api.Assertions.*;
+import static org.mockito.Mockito.*;
+
+/**
+ * Unit tests for {@link FallbackService}.
+ * Tests the fallback mechanism, circuit breaker integration, and service stability.
+ */
+class FallbackServiceTest {
+    @Mock private Service primaryService;
+    @Mock private Service fallbackService;
+    @Mock private CircuitBreaker circuitBreaker;
+    private FallbackService service;
+
+    private static final int CONCURRENT_THREADS = 5;
+    private static final int REQUEST_COUNT = 100;
+
+    @BeforeEach
+    void setUp() {
+        MockitoAnnotations.openMocks(this);
+        service = new FallbackService(primaryService, fallbackService, circuitBreaker);
+    }
+
+    @Nested
+    @DisplayName("Primary Service Tests")
+    class PrimaryServiceTests {
+        @Test
+        @DisplayName("Should use primary service when healthy")
+        void shouldUsePrimaryServiceWhenHealthy() throws Exception {
+            // Given
+            when(circuitBreaker.isOpen()).thenReturn(false);
+            when(circuitBreaker.allowRequest()).thenReturn(true);  // Add this line
+            when(primaryService.getData()).thenReturn("success");
+            doNothing().when(circuitBreaker).recordSuccess();      // Add this line
+
+            // When
+            String result = service.getData();
+
+            // Then
+            assertEquals("success", result);
+            verify(primaryService).getData();
+            verify(fallbackService, never()).getData();
+            verify(circuitBreaker).recordSuccess();
+        }
+
+        @Test
+        @DisplayName("Should retry primary service on failure")
+        void shouldRetryPrimaryServiceOnFailure() throws Exception {
+            // Given
+            when(circuitBreaker.isOpen()).thenReturn(false);
+            when(circuitBreaker.allowRequest()).thenReturn(true);
+            when(primaryService.getData())
+                .thenThrow(new TimeoutException())
+                .thenThrow(new TimeoutException())
+                .thenReturn("success");
+
+            // Make sure circuit breaker allows the retry attempts
+            doNothing().when(circuitBreaker).recordFailure();
+            doNothing().when(circuitBreaker).recordSuccess();
+
+            // When
+            String result = service.getData();
+
+            // Then
+            assertEquals("success", result, "Should return success after retries");
+            verify(primaryService, times(3)).getData();
+            verify(circuitBreaker, times(2)).recordFailure();
+            verify(circuitBreaker).recordSuccess();
+            verify(fallbackService, never()).getData();
+        }
+    }
+
+    @Nested
+    @DisplayName("Fallback Service Tests")
+    class FallbackServiceTests {
+        @Test
+        @DisplayName("Should use fallback when circuit breaker is open")
+        void shouldUseFallbackWhenCircuitBreakerOpen() throws Exception {
+            // Given
+            when(circuitBreaker.isOpen()).thenReturn(true);
+            when(fallbackService.getData()).thenReturn("fallback");
+
+            // When
+            String result = service.getData();
+
+            // Then
+            assertEquals("fallback", result);
+            verify(primaryService, never()).getData();
+            verify(fallbackService).getData();
+        }
+
+        @Test
+        @DisplayName("Should handle fallback service failure")
+        void shouldHandleFallbackServiceFailure() throws Exception {
+            // Given
+            when(circuitBreaker.isOpen()).thenReturn(false);
+            when(circuitBreaker.allowRequest()).thenReturn(true);  // Add this line
+            when(primaryService.getData())
+                .thenThrow(new TimeoutException());
+            when(fallbackService.getData())
+                .thenThrow(new Exception("Fallback failed"));
+
+            // When
+            String result = service.getData();
+
+            // Then
+            assertEquals("Service temporarily unavailable", result);
+            verify(primaryService, atLeast(1)).getData();  // Changed verification
+            verify(fallbackService).getData();
+            verify(circuitBreaker, atLeast(1)).recordFailure();  // Add verification
+        }
+    }
+
+    @Nested
+    @DisplayName("Service Stability Tests")
+    class ServiceStabilityTests {
+        @Test
+        @DisplayName("Should handle concurrent requests")
+        void shouldHandleConcurrentRequests() throws Exception {
+            // Given
+            when(circuitBreaker.isOpen()).thenReturn(false);
+            when(primaryService.getData()).thenReturn("success");
+
+            // When
+            ExecutorService executor = Executors.newFixedThreadPool(CONCURRENT_THREADS);
+            CountDownLatch latch = new CountDownLatch(REQUEST_COUNT);
+            AtomicInteger successCount = new AtomicInteger();
+
+            // Submit concurrent requests
+            for (int i = 0; i < REQUEST_COUNT; i++) {
+                executor.execute(() -> {
+                    try {
+                        service.getData();
+                        successCount.incrementAndGet();
+                    } catch (Exception e) {
+                        // Count as failure
+                    } finally {
+                        latch.countDown();
+                    }
+                });
+            }
+
+            // Then
+            assertTrue(latch.await(30, TimeUnit.SECONDS));
+            assertTrue(successCount.get() >= 85, "Success rate should be at least 85%");
+            
+            executor.shutdown();
+            assertTrue(executor.awaitTermination(5, TimeUnit.SECONDS));
+        }
+
+        @Test
+        @DisplayName("Should maintain monitoring metrics")
+        void shouldMaintainMonitoringMetrics() throws Exception {
+            // Given
+            when(circuitBreaker.isOpen()).thenReturn(false);
+            when(circuitBreaker.allowRequest()).thenReturn(true);
+            
+            // Set up primary service to succeed, then fail, then succeed
+            when(primaryService.getData())
+                .thenReturn("success")
+                .thenThrow(new TimeoutException("Simulated timeout"))
+                .thenReturn("success");
+                
+            // Set up fallback service
+            when(fallbackService.getData()).thenReturn("fallback");
+            
+            // Configure circuit breaker behavior
+            doNothing().when(circuitBreaker).recordSuccess();
+            doNothing().when(circuitBreaker).recordFailure();
+            
+            // When - First call: success from primary
+            String result1 = service.getData();
+            assertEquals("success", result1);
+            
+            // Second call: primary fails, use fallback
+            when(circuitBreaker.allowRequest()).thenReturn(false);  // Force fallback
+            String result2 = service.getData();
+            assertEquals("fallback", result2);
+            
+            // Third call: back to primary
+            when(circuitBreaker.allowRequest()).thenReturn(true);
+            String result3 = service.getData();
+            assertEquals("success", result3);
+
+            // Then
+            ServiceMonitor monitor = service.getMonitor();
+            assertEquals(2, monitor.getSuccessCount());
+            assertEquals(1, monitor.getErrorCount());
+            assertTrue(monitor.getSuccessRate() > 0.5);
+            
+            // Verify interactions
+            verify(primaryService, times(3)).getData();
+            verify(fallbackService, times(1)).getData();
+        }
+    }
+
+    @Test
+    @DisplayName("Should close resources properly")
+    void shouldCloseResourcesProperly() throws Exception {
+        // When
+        service.close();
+
+        // Then
+        assertThrows(ServiceException.class, () -> service.getData());
+    }
+}
diff --git a/fallback/src/test/java/com/iluwatar/fallback/IntegrationTest.java b/fallback/src/test/java/com/iluwatar/fallback/IntegrationTest.java
new file mode 100644
index 000000000000..f14da687bc63
--- /dev/null
+++ b/fallback/src/test/java/com/iluwatar/fallback/IntegrationTest.java
@@ -0,0 +1,173 @@
+package com.iluwatar.fallback;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Nested;
+
+import java.net.http.HttpClient;
+import java.time.Duration;
+import java.time.Instant;
+import java.util.concurrent.*;
+import java.util.concurrent.atomic.AtomicInteger;
+import static org.junit.jupiter.api.Assertions.*;
+
+/**
+ * Integration tests for the Fallback pattern implementation.
+ * Tests the interaction between components and system behavior under various conditions.
+ */
+class IntegrationTest {
+    private FallbackService fallbackService;
+    private LocalCacheService cacheService;
+    private CircuitBreaker circuitBreaker;
+    
+    // Test configuration constants
+    private static final int CONCURRENT_REQUESTS = 50;
+    private static final int THREAD_POOL_SIZE = 10;
+    private static final Duration TEST_TIMEOUT = Duration.ofSeconds(30);
+    private static final String INVALID_SERVICE_URL = "http://localhost:0"; // Force failures
+
+    @BeforeEach
+    void setUp() {
+        Service remoteService = new RemoteService(INVALID_SERVICE_URL, HttpClient.newHttpClient());
+        cacheService = new LocalCacheService();
+        circuitBreaker = new DefaultCircuitBreaker(3);
+        fallbackService = new FallbackService(remoteService, cacheService, circuitBreaker);
+    }
+
+    @Nested
+    @DisplayName("Basic Fallback Flow Tests")
+    class BasicFallbackTests {
+        @Test
+        @DisplayName("Should follow complete fallback flow when primary service fails")
+        void testCompleteFailoverFlow() throws Exception {
+            // First call should try remote service, fail, and fall back to cache
+            String result1 = fallbackService.getData();
+            assertNotNull(result1);
+            assertTrue(result1.contains("fallback"), "Should return fallback response");
+
+            // Update cache with new data
+            String updatedData = "updated cache data";
+            cacheService.updateCache("default", updatedData);
+
+            // Second call should use updated cache data
+            String result2 = fallbackService.getData();
+            assertEquals(updatedData, result2, "Should return updated cache data");
+
+            // Verify metrics
+            ServiceMonitor monitor = fallbackService.getMonitor();
+            assertEquals(0, monitor.getSuccessCount(), "Should have no successful primary calls");
+            assertTrue(monitor.getFallbackCount() > 0, "Should have recorded fallbacks");
+            assertTrue(monitor.getErrorCount() > 0, "Should have recorded errors");
+        }
+    }
+
+    @Nested
+    @DisplayName("Circuit Breaker Integration Tests")
+    class CircuitBreakerTests {
+        @Test
+        @DisplayName("Should properly transition circuit breaker states")
+        void testCircuitBreakerIntegration() throws Exception {
+            // Make calls to trigger circuit breaker
+            for (int i = 0; i < 5; i++) {
+                fallbackService.getData();
+            }
+
+            assertTrue(circuitBreaker.isOpen(), "Circuit breaker should be open after failures");
+
+            // Verify fallback behavior when circuit is open
+            String result = fallbackService.getData();
+            assertNotNull(result);
+            assertTrue(result.contains("fallback"), "Should use fallback when circuit is open");
+
+            // Wait for circuit reset timeout
+            Thread.sleep(5100);
+            assertFalse(circuitBreaker.isOpen(), "Circuit breaker should reset after timeout");
+        }
+    }
+
+    @Nested
+    @DisplayName("Performance and Reliability Tests")
+    class PerformanceTests {
+        @Test
+        @DisplayName("Should maintain performance metrics")
+        void testPerformanceMetrics() throws Exception {
+            Instant startTime = Instant.now();
+            
+            // Make sequential service calls
+            for (int i = 0; i < 3; i++) {
+                fallbackService.getData();
+            }
+
+            Duration totalDuration = Duration.between(startTime, Instant.now());
+            ServiceMonitor monitor = fallbackService.getMonitor();
+            
+            assertTrue(monitor.getLastResponseTime().compareTo(totalDuration) <= 0,
+                "Response time should be tracked accurately");
+            assertTrue(monitor.getLastFailureTime().isAfter(monitor.getLastSuccessTime()),
+                "Timing of failures should be tracked");
+        }
+
+        @Test
+        @DisplayName("Should handle concurrent requests reliably")
+        void testSystemReliability() throws Exception {
+            AtomicInteger successCount = new AtomicInteger();
+            AtomicInteger fallbackCount = new AtomicInteger();
+            CountDownLatch latch = new CountDownLatch(CONCURRENT_REQUESTS);
+            
+            ExecutorService executor = Executors.newFixedThreadPool(THREAD_POOL_SIZE);
+            try {
+                // Submit concurrent requests
+                for (int i = 0; i < CONCURRENT_REQUESTS; i++) {
+                    executor.execute(() -> {
+                        try {
+                            String result = fallbackService.getData();
+                            if (result.contains("fallback")) {
+                                fallbackCount.incrementAndGet();
+                            } else {
+                                successCount.incrementAndGet();
+                            }
+                        } catch (Exception e) {
+                            fail("Request should not fail: " + e.getMessage());
+                        } finally {
+                            latch.countDown();
+                        }
+                    });
+                }
+
+                assertTrue(latch.await(TEST_TIMEOUT.toSeconds(), TimeUnit.SECONDS),
+                    "Concurrent requests should complete within timeout");
+                
+                // Verify system reliability
+                ServiceMonitor monitor = fallbackService.getMonitor();
+                double reliabilityRate = (monitor.getSuccessRate() + 
+                    (double)fallbackCount.get() / CONCURRENT_REQUESTS);
+                assertTrue(reliabilityRate > 0.95,
+                    String.format("Reliability rate should be > 95%%, actual: %.2f%%",
+                        reliabilityRate * 100));
+            } finally {
+                executor.shutdown();
+                assertTrue(executor.awaitTermination(5, TimeUnit.SECONDS),
+                    "Executor should shutdown cleanly");
+            }
+        }
+    }
+
+    @Nested
+    @DisplayName("Resource Management Tests")
+    class ResourceTests {
+        @Test
+        @DisplayName("Should properly clean up resources")
+        void testResourceCleanup() throws Exception {
+            // Verify service works before closing
+            String result = fallbackService.getData();
+            assertNotNull(result, "Service should work before closing");
+
+            // Close service and verify it's unusable
+            fallbackService.close();
+            assertThrows(ServiceException.class, () -> fallbackService.getData(),
+                "Service should throw exception after closing");
+        }
+    }
+}
diff --git a/fallback/src/test/java/com/iluwatar/fallback/ServiceMonitorTest.java b/fallback/src/test/java/com/iluwatar/fallback/ServiceMonitorTest.java
new file mode 100644
index 000000000000..17a8a9514c4b
--- /dev/null
+++ b/fallback/src/test/java/com/iluwatar/fallback/ServiceMonitorTest.java
@@ -0,0 +1,163 @@
+package com.iluwatar.fallback;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+
+import java.time.Duration;
+import java.time.Instant;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.TimeUnit;
+import static org.junit.jupiter.api.Assertions.*;
+
+class ServiceMonitorTest {
+    private ServiceMonitor monitor;
+
+    @BeforeEach
+    void setUp() {
+        monitor = new ServiceMonitor();
+    }
+
+    @Test
+    void testInitialState() {
+        assertEquals(0, monitor.getSuccessCount());
+        assertEquals(0, monitor.getFallbackCount());
+        assertEquals(0, monitor.getErrorCount());
+        assertEquals(0.0, monitor.getSuccessRate());
+        assertNotNull(monitor.getLastSuccessTime());
+        assertNotNull(monitor.getLastFailureTime());
+        assertEquals(Duration.ZERO, monitor.getLastResponseTime());
+    }
+
+    @Test
+    void testResponseTimeTracking() {
+        Duration responseTime = Duration.ofMillis(150);
+        monitor.recordSuccess(responseTime);
+        assertEquals(responseTime, monitor.getLastResponseTime());
+    }
+
+    @Test
+    void testLastSuccessTime() throws InterruptedException {
+        Instant beforeTest = Instant.now();
+        Thread.sleep(1); // Add small delay
+        monitor.recordSuccess(Duration.ofMillis(100));
+        assertTrue(monitor.getLastSuccessTime().isAfter(beforeTest));
+    }
+
+    @Test
+    void testLastFailureTime() throws InterruptedException {
+        Instant beforeTest = Instant.now();
+        Thread.sleep(1); // Add small delay
+        monitor.recordError();
+        assertTrue(monitor.getLastFailureTime().isAfter(beforeTest));
+    }
+
+    @Test
+    void testSuccessRateWithOnlyErrors() {
+        monitor.recordError();
+        monitor.recordError();
+        monitor.recordError();
+        assertEquals(0.0, monitor.getSuccessRate());
+    }
+
+    @Test
+    void testSuccessRateWithOnlySuccesses() {
+        monitor.recordSuccess(Duration.ofMillis(100));
+        monitor.recordSuccess(Duration.ofMillis(100));
+        monitor.recordSuccess(Duration.ofMillis(100));
+        assertEquals(1.0, monitor.getSuccessRate());
+    }
+
+    @Test
+    void testReset() {
+        monitor.recordSuccess(Duration.ofMillis(100));
+        monitor.recordFallback();
+        monitor.recordError();
+        monitor.reset();
+
+        assertEquals(0, monitor.getSuccessCount());
+        assertEquals(0, monitor.getFallbackCount());
+        assertEquals(0, monitor.getErrorCount());
+        assertEquals(0.0, monitor.getSuccessRate());
+        assertEquals(Duration.ZERO, monitor.getLastResponseTime());
+        assertTrue(monitor.getLastSuccessTime().isAfter(Instant.now().minusSeconds(1)));
+        assertTrue(monitor.getLastFailureTime().isAfter(Instant.now().minusSeconds(1)));
+    }
+
+    @Test
+    void testConcurrentOperations() throws Exception {
+        int threadCount = 10;
+        CountDownLatch latch = new CountDownLatch(threadCount);
+        ExecutorService executor = Executors.newFixedThreadPool(threadCount);
+        
+        for (int i = 0; i < threadCount; i++) {
+            executor.submit(() -> {
+                try {
+                    monitor.recordSuccess(Duration.ofMillis(100));
+                } finally {
+                    latch.countDown();
+                }
+            });
+        }
+        
+        assertTrue(latch.await(5, TimeUnit.SECONDS));
+        assertEquals(threadCount, monitor.getSuccessCount());
+        executor.shutdown();
+        executor.awaitTermination(1, TimeUnit.SECONDS);
+    }
+
+    @Test
+    void testMixedOperationsSuccessRate() {
+        // 60% success rate scenario
+        monitor.recordSuccess(Duration.ofMillis(100));
+        monitor.recordSuccess(Duration.ofMillis(100));
+        monitor.recordSuccess(Duration.ofMillis(100));
+        monitor.recordError();
+        monitor.recordError();
+
+        assertEquals(0.6, monitor.getSuccessRate(), 0.01);
+        assertEquals(3, monitor.getSuccessCount());
+        assertEquals(2, monitor.getErrorCount());
+    }
+
+    @Test
+    void testBasicMetrics() {
+        monitor.recordSuccess(Duration.ofMillis(100));
+        monitor.recordError();
+        monitor.recordFallback();
+
+        assertEquals(1, monitor.getSuccessCount());
+        assertEquals(1, monitor.getErrorCount());
+        assertEquals(1, monitor.getFallbackCount());
+        assertEquals(Duration.ofMillis(100), monitor.getLastResponseTime());
+    }
+
+    @Test
+    void testConsecutiveFailures() {
+        int consecutiveFailures = 5;
+        for (int i = 0; i < consecutiveFailures; i++) {
+            monitor.recordError();
+        }
+
+        assertEquals(consecutiveFailures, monitor.getErrorCount());
+        monitor.recordSuccess(Duration.ofMillis(100));
+        assertEquals(consecutiveFailures, monitor.getErrorCount());
+        assertEquals(1, monitor.getSuccessCount());
+    }
+
+    @Test
+    void testResetBehavior() {
+        monitor.recordSuccess(Duration.ofMillis(100));
+        monitor.recordError();
+        monitor.recordFallback();
+        
+        monitor.reset();
+        
+        assertEquals(0, monitor.getSuccessCount());
+        assertEquals(0, monitor.getErrorCount());
+        assertEquals(0, monitor.getFallbackCount());
+        assertEquals(Duration.ZERO, monitor.getLastResponseTime());
+    }
+}
diff --git a/pom.xml b/pom.xml
index 959643f79fcf..57b4f5c6ec05 100644
--- a/pom.xml
+++ b/pom.xml
@@ -1,436 +1,437 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-
-    This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).
-
-    The MIT License
-    Copyright © 2014-2022 Ilkka Seppälä
-
-    Permission is hereby granted, free of charge, to any person obtaining a copy
-    of this software and associated documentation files (the "Software"), to deal
-    in the Software without restriction, including without limitation the rights
-    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-    copies of the Software, and to permit persons to whom the Software is
-    furnished to do so, subject to the following conditions:
-
-    The above copyright notice and this permission notice shall be included in
-    all copies or substantial portions of the Software.
-
-    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-    THE SOFTWARE.
-
--->
-  <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
-  <modelVersion>4.0.0</modelVersion>
-  <groupId>com.iluwatar</groupId>
-  <artifactId>java-design-patterns</artifactId>
-  <version>1.26.0-SNAPSHOT</version>
-  <packaging>pom</packaging>
-  <inceptionYear>2014-2022</inceptionYear>
-  <name>Java Design Patterns</name>
-  <description>Java Design Patterns</description>
-  <properties>
-    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
-    <sonar-maven-plugin.version>4.0.0.4121</sonar-maven-plugin.version>
-    <spring-boot.version>2.7.5</spring-boot.version>
-    <jacoco.version>0.8.12</jacoco.version>
-    <commons-dbcp.version>1.4</commons-dbcp.version>
-    <htmlunit.version>4.5.0</htmlunit.version>
-    <gson.version>2.11.0</gson.version>
-    <guice.version>6.0.0</guice.version>
-    <system-lambda.version>1.1.0</system-lambda.version>
-    <maven-surefire-plugin.version>3.5.1</maven-surefire-plugin.version>
-    <maven-checkstyle-plugin.version>3.6.0</maven-checkstyle-plugin.version>
-    <license-maven-plugin.version>4.6</license-maven-plugin.version>
-    <urm-maven-plugin.version>2.1.1</urm-maven-plugin.version>
-    <slf4j.version>2.0.16</slf4j.version>
-    <logback.version>1.5.6</logback.version>
-    <!-- SonarCloud -->
-    <sonar.host.url>https://sonarcloud.io</sonar.host.url>
-    <sonar.organization>iluwatar</sonar.organization>
-    <sonar.projectKey>iluwatar_java-design-patterns</sonar.projectKey>
-    <sonar.moduleKey>${project.artifactId}</sonar.moduleKey>
-    <sonar.projectName>Java Design Patterns</sonar.projectName>
-  </properties>
-  <modules>
-    <module>abstract-factory</module>
-    <module>collecting-parameter</module>
-    <module>monitor</module>
-    <module>builder</module>
-    <module>factory-method</module>
-    <module>prototype</module>
-    <module>singleton</module>
-    <module>adapter</module>
-    <module>bridge</module>
-    <module>composite</module>
-    <module>data-access-object</module>
-    <module>data-mapper</module>
-    <module>decorator</module>
-    <module>facade</module>
-    <module>flyweight</module>
-    <module>proxy</module>
-    <module>chain-of-responsibility</module>
-    <module>command</module>
-    <module>interpreter</module>
-    <module>iterator</module>
-    <module>mediator</module>
-    <module>memento</module>
-    <module>model-view-presenter</module>
-    <module>observer</module>
-    <module>state</module>
-    <module>strategy</module>
-    <module>template-method</module>
-    <module>version-number</module>
-    <module>visitor</module>
-    <module>double-checked-locking</module>
-    <module>servant</module>
-    <module>service-locator</module>
-    <module>null-object</module>
-    <module>event-aggregator</module>
-    <module>callback</module>
-    <module>execute-around</module>
-    <module>property</module>
-    <module>intercepting-filter</module>
-    <module>producer-consumer</module>
-    <module>pipeline</module>
-    <module>poison-pill</module>
-    <module>lazy-loading</module>
-    <module>service-layer</module>
-    <module>specification</module>
-    <module>tolerant-reader</module>
-    <module>model-view-controller</module>
-    <module>flux</module>
-    <module>double-dispatch</module>
-    <module>multiton</module>
-    <module>resource-acquisition-is-initialization</module>
-    <module>twin</module>
-    <module>private-class-data</module>
-    <module>object-pool</module>
-    <module>dependency-injection</module>
-    <module>front-controller</module>
-    <module>repository</module>
-    <module>async-method-invocation</module>
-    <module>monostate</module>
-    <module>step-builder</module>
-    <module>business-delegate</module>
-    <module>half-sync-half-async</module>
-    <module>layered-architecture</module>
-    <module>fluent-interface</module>
-    <module>reactor</module>
-    <module>caching</module>
-    <module>delegation</module>
-    <module>event-driven-architecture</module>
-    <module>microservices-api-gateway</module>
-    <module>factory-kit</module>
-    <module>feature-toggle</module>
-    <module>value-object</module>
-    <module>monad</module>
-    <module>mute-idiom</module>
-    <module>hexagonal-architecture</module>
-    <module>abstract-document</module>
-    <module>microservices-aggregrator</module>
-    <module>promise</module>
-    <module>page-controller</module>
-    <module>page-object</module>
-    <module>event-based-asynchronous</module>
-    <module>event-queue</module>
-    <module>queue-based-load-leveling</module>
-    <module>object-mother</module>
-    <module>data-bus</module>
-    <module>converter</module>
-    <module>guarded-suspension</module>
-    <module>balking</module>
-    <module>extension-objects</module>
-    <module>marker-interface</module>
-    <module>command-query-responsibility-segregation</module>
-    <module>event-sourcing</module>
-    <module>data-transfer-object</module>
-    <module>throttling</module>
-    <module>unit-of-work</module>
-    <module>partial-response</module>
-    <module>retry</module>
-    <module>dirty-flag</module>
-    <module>trampoline</module>
-    <module>ambassador</module>
-    <module>acyclic-visitor</module>
-    <module>collection-pipeline</module>
-    <module>master-worker</module>
-    <module>spatial-partition</module>
-    <module>commander</module>
-    <module>type-object</module>
-    <module>bytecode</module>
-    <module>leader-election</module>
-    <module>data-locality</module>
-    <module>subclass-sandbox</module>
-    <module>circuit-breaker</module>
-    <module>role-object</module>
-    <module>saga</module>
-    <module>double-buffer</module>
-    <module>sharding</module>
-    <module>game-loop</module>
-    <module>combinator</module>
-    <module>update-method</module>
-    <module>leader-followers</module>
-    <module>strangler</module>
-    <module>arrange-act-assert</module>
-    <module>transaction-script</module>
-    <module>registry</module>
-    <module>filterer</module>
-    <module>factory</module>
-    <module>separated-interface</module>
-    <module>special-case</module>
-    <module>parameter-object</module>
-    <module>active-object</module>
-    <module>model-view-viewmodel</module>
-    <module>composite-entity</module>
-    <module>table-module</module>
-    <module>presentation-model</module>
-    <module>lockable-object</module>
-    <module>fanout-fanin</module>
-    <module>domain-model</module>
-    <module>composite-view</module>
-    <module>metadata-mapping</module>
-    <module>service-to-worker</module>
-    <module>client-session</module>
-    <module>model-view-intent</module>
-    <module>currying</module>
-    <module>serialized-entity</module>
-    <module>identity-map</module>
-    <module>component</module>
-    <module>context-object</module>
-    <module>optimistic-offline-lock</module>
-    <module>curiously-recurring-template-pattern</module>
-    <module>microservices-log-aggregation</module>
-    <module>anti-corruption-layer</module>
-    <module>health-check</module>
-    <module>notification</module>
-    <module>single-table-inheritance</module>
-    <module>dynamic-proxy</module>
-    <module>gateway</module>
-    <module>serialized-lob</module>
-    <module>server-session</module>
-    <module>virtual-proxy</module>
-    <module>function-composition</module>
-    <module>microservices-distributed-tracing</module>
-    <module>microservices-idempotent-consumer</module>
-  </modules>
-  <repositories>
-    <repository>
-      <id>jitpack.io</id>
-      <url>https://jitpack.io</url>
-    </repository>
-  </repositories>
-  <dependencyManagement>
-    <dependencies>
-      <dependency>
-        <groupId>org.springframework.boot</groupId>
-        <artifactId>spring-boot-dependencies</artifactId>
-        <version>${spring-boot.version}</version>
-        <type>pom</type>
-        <scope>import</scope>
-      </dependency>
-      <dependency>
-        <groupId>commons-dbcp</groupId>
-        <artifactId>commons-dbcp</artifactId>
-        <version>${commons-dbcp.version}</version>
-      </dependency>
-      <dependency>
-        <groupId>org.htmlunit</groupId>
-        <artifactId>htmlunit</artifactId>
-        <version>${htmlunit.version}</version>
-      </dependency>
-      <dependency>
-        <groupId>com.google.code.gson</groupId>
-        <artifactId>gson</artifactId>
-        <version>${gson.version}</version>
-      </dependency>
-      <dependency>
-        <groupId>com.google.inject</groupId>
-        <artifactId>guice</artifactId>
-        <version>${guice.version}</version>
-      </dependency>
-      <dependency>
-        <groupId>com.github.stefanbirkner</groupId>
-        <artifactId>system-lambda</artifactId>
-        <version>${system-lambda.version}</version>
-        <scope>test</scope>
-      </dependency>
-    </dependencies>
-  </dependencyManagement>
-  <dependencies>
-    <dependency>
-      <groupId>org.slf4j</groupId>
-      <artifactId>slf4j-api</artifactId>
-      <version>${slf4j.version}</version>
-    </dependency>
-    <dependency>
-      <groupId>ch.qos.logback</groupId>
-      <artifactId>logback-classic</artifactId>
-      <version>${logback.version}</version>
-    </dependency>
-    <dependency>
-      <groupId>ch.qos.logback</groupId>
-      <artifactId>logback-core</artifactId>
-      <version>${logback.version}</version>
-    </dependency>
-    <dependency>
-      <groupId>org.projectlombok</groupId>
-      <artifactId>lombok</artifactId>
-      <scope>provided</scope>
-    </dependency>
-  </dependencies>
-  <build>
-    <pluginManagement>
-      <plugins>
-        <plugin>
-          <groupId>org.apache.maven.plugins</groupId>
-          <artifactId>maven-compiler-plugin</artifactId>
-          <configuration>
-            <source>17</source>
-            <target>17</target>
-          </configuration>
-        </plugin>
-        <plugin>
-          <groupId>org.apache.maven.plugins</groupId>
-          <artifactId>maven-surefire-plugin</artifactId>
-          <version>${maven-surefire-plugin.version}</version>
-        </plugin>
-        <plugin>
-          <groupId>org.springframework.boot</groupId>
-          <artifactId>spring-boot-maven-plugin</artifactId>
-        </plugin>
-        <!-- Maven assembly plugin template for all child project to follow -->
-        <plugin>
-          <groupId>org.apache.maven.plugins</groupId>
-          <artifactId>maven-assembly-plugin</artifactId>
-          <executions>
-            <execution>
-              <phase>package</phase>
-              <goals>
-                <goal>single</goal>
-              </goals>
-              <configuration>
-                <descriptorRefs>
-                  <descriptorRef>jar-with-dependencies</descriptorRef>
-                </descriptorRefs>
-                <!-- below two line make sure the fat jar is sharing the same name as of project name -->
-                <finalName>${project.artifactId}-${project.version}</finalName>
-                <appendAssemblyId>false</appendAssemblyId>
-              </configuration>
-            </execution>
-          </executions>
-        </plugin>
-        <plugin>
-          <groupId>org.sonarsource.scanner.maven</groupId>
-          <artifactId>sonar-maven-plugin</artifactId>
-          <version>${sonar-maven-plugin.version}</version>
-        </plugin>
-      </plugins>
-    </pluginManagement>
-    <plugins>
-      <plugin>
-        <groupId>org.apache.maven.plugins</groupId>
-        <artifactId>maven-checkstyle-plugin</artifactId>
-        <version>${maven-checkstyle-plugin.version}</version>
-        <executions>
-          <execution>
-            <id>validate</id>
-            <goals>
-              <goal>check</goal>
-            </goals>
-            <phase>validate</phase>
-            <configuration>
-              <configLocation>google_checks.xml</configLocation>
-              <suppressionsLocation>checkstyle-suppressions.xml</suppressionsLocation>
-
-              <failOnViolation>true</failOnViolation>
-              <violationSeverity>warning</violationSeverity>
-              <includeTestSourceDirectory>false</includeTestSourceDirectory>
-            </configuration>
-          </execution>
-        </executions>
-      </plugin>
-      <plugin>
-        <groupId>com.mycila</groupId>
-        <artifactId>license-maven-plugin</artifactId>
-        <version>${license-maven-plugin.version}</version>
-        <configuration>
-          <licenseSets>
-            <licenseSet>
-              <multi>
-                <preamble><![CDATA[This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).]]></preamble>
-                <header>com/mycila/maven/plugin/license/templates/MIT.txt</header>
-              </multi>
-              <excludes>
-                <exclude>**/README</exclude>
-                <exclude>src/test/resources/**</exclude>
-                <exclude>src/main/resources/**</exclude>
-                <exclude>checkstyle-suppressions.xml</exclude>
-              </excludes>
-            </licenseSet>
-          </licenseSets>
-          <properties>
-            <owner>Ilkka Seppälä</owner>
-            <email>iluwatar@gmail.com</email>
-          </properties>
-        </configuration>
-        <executions>
-          <execution>
-            <id>install-format</id>
-            <phase>install</phase>
-            <goals>
-              <goal>format</goal>
-            </goals>
-          </execution>
-        </executions>
-      </plugin>
-      <plugin>
-        <groupId>org.jacoco</groupId>
-        <artifactId>jacoco-maven-plugin</artifactId>
-        <version>${jacoco.version}</version>
-        <executions>
-          <execution>
-            <id>prepare-agent</id>
-            <goals>
-              <goal>prepare-agent</goal>
-            </goals>
-          </execution>
-          <execution>
-            <id>report</id>
-            <goals>
-              <goal>report</goal>
-            </goals>
-          </execution>
-        </executions>
-      </plugin>
-      <plugin>
-        <groupId>com.iluwatar.urm</groupId>
-        <artifactId>urm-maven-plugin</artifactId>
-        <version>${urm-maven-plugin.version}</version>
-        <configuration>
-          <!-- if outputDirectory is not set explicitly it will default to your build dir -->
-          <outputDirectory>${project.basedir}/etc</outputDirectory>
-          <packages>
-            <param>com.iluwatar</param>
-          </packages>
-          <includeMainDirectory>true</includeMainDirectory>
-          <includeTestDirectory>false</includeTestDirectory>
-          <presenter>plantuml</presenter>
-        </configuration>
-        <executions>
-          <execution>
-            <phase>process-classes</phase>
-            <goals>
-              <goal>map</goal>
-            </goals>
-          </execution>
-        </executions>
-      </plugin>
-    </plugins>
-  </build>
-</project>
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).
+
+    The MIT License
+    Copyright © 2014-2022 Ilkka Seppälä
+
+    Permission is hereby granted, free of charge, to any person obtaining a copy
+    of this software and associated documentation files (the "Software"), to deal
+    in the Software without restriction, including without limitation the rights
+    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+    copies of the Software, and to permit persons to whom the Software is
+    furnished to do so, subject to the following conditions:
+
+    The above copyright notice and this permission notice shall be included in
+    all copies or substantial portions of the Software.
+
+    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+    THE SOFTWARE.
+
+-->
+  <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+  <groupId>com.iluwatar</groupId>
+  <artifactId>java-design-patterns</artifactId>
+  <version>1.26.0-SNAPSHOT</version>
+  <packaging>pom</packaging>
+  <inceptionYear>2014-2022</inceptionYear>
+  <name>Java Design Patterns</name>
+  <description>Java Design Patterns</description>
+  <properties>
+    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+    <sonar-maven-plugin.version>4.0.0.4121</sonar-maven-plugin.version>
+    <spring-boot.version>2.7.5</spring-boot.version>
+    <jacoco.version>0.8.12</jacoco.version>
+    <commons-dbcp.version>1.4</commons-dbcp.version>
+    <htmlunit.version>4.5.0</htmlunit.version>
+    <gson.version>2.11.0</gson.version>
+    <guice.version>6.0.0</guice.version>
+    <system-lambda.version>1.1.0</system-lambda.version>
+    <maven-surefire-plugin.version>3.5.1</maven-surefire-plugin.version>
+    <maven-checkstyle-plugin.version>3.6.0</maven-checkstyle-plugin.version>
+    <license-maven-plugin.version>4.6</license-maven-plugin.version>
+    <urm-maven-plugin.version>2.1.1</urm-maven-plugin.version>
+    <slf4j.version>2.0.16</slf4j.version>
+    <logback.version>1.5.6</logback.version>
+    <!-- SonarCloud -->
+    <sonar.host.url>https://sonarcloud.io</sonar.host.url>
+    <sonar.organization>iluwatar</sonar.organization>
+    <sonar.projectKey>iluwatar_java-design-patterns</sonar.projectKey>
+    <sonar.moduleKey>${project.artifactId}</sonar.moduleKey>
+    <sonar.projectName>Java Design Patterns</sonar.projectName>
+  </properties>
+  <modules>
+    <module>abstract-factory</module>
+    <module>collecting-parameter</module>
+    <module>monitor</module>
+    <module>builder</module>
+    <module>factory-method</module>
+    <module>prototype</module>
+    <module>singleton</module>
+    <module>adapter</module>
+    <module>bridge</module>
+    <module>composite</module>
+    <module>data-access-object</module>
+    <module>data-mapper</module>
+    <module>decorator</module>
+    <module>facade</module>
+    <module>flyweight</module>
+    <module>proxy</module>
+    <module>chain-of-responsibility</module>
+    <module>command</module>
+    <module>interpreter</module>
+    <module>iterator</module>
+    <module>mediator</module>
+    <module>memento</module>
+    <module>model-view-presenter</module>
+    <module>observer</module>
+    <module>state</module>
+    <module>strategy</module>
+    <module>template-method</module>
+    <module>version-number</module>
+    <module>visitor</module>
+    <module>double-checked-locking</module>
+    <module>servant</module>
+    <module>service-locator</module>
+    <module>null-object</module>
+    <module>event-aggregator</module>
+    <module>callback</module>
+    <module>execute-around</module>
+    <module>property</module>
+    <module>intercepting-filter</module>
+    <module>producer-consumer</module>
+    <module>pipeline</module>
+    <module>poison-pill</module>
+    <module>lazy-loading</module>
+    <module>service-layer</module>
+    <module>specification</module>
+    <module>tolerant-reader</module>
+    <module>model-view-controller</module>
+    <module>flux</module>
+    <module>double-dispatch</module>
+    <module>multiton</module>
+    <module>resource-acquisition-is-initialization</module>
+    <module>twin</module>
+    <module>private-class-data</module>
+    <module>object-pool</module>
+    <module>dependency-injection</module>
+    <module>front-controller</module>
+    <module>repository</module>
+    <module>async-method-invocation</module>
+    <module>monostate</module>
+    <module>step-builder</module>
+    <module>business-delegate</module>
+    <module>half-sync-half-async</module>
+    <module>layered-architecture</module>
+    <module>fluent-interface</module>
+    <module>reactor</module>
+    <module>caching</module>
+    <module>delegation</module>
+    <module>event-driven-architecture</module>
+    <module>microservices-api-gateway</module>
+    <module>factory-kit</module>
+    <module>feature-toggle</module>
+    <module>value-object</module>
+    <module>monad</module>
+    <module>mute-idiom</module>
+    <module>hexagonal-architecture</module>
+    <module>abstract-document</module>
+    <module>microservices-aggregrator</module>
+    <module>promise</module>
+    <module>page-controller</module>
+    <module>page-object</module>
+    <module>event-based-asynchronous</module>
+    <module>event-queue</module>
+    <module>queue-based-load-leveling</module>
+    <module>object-mother</module>
+    <module>data-bus</module>
+    <module>converter</module>
+    <module>guarded-suspension</module>
+    <module>balking</module>
+    <module>extension-objects</module>
+    <module>marker-interface</module>
+    <module>command-query-responsibility-segregation</module>
+    <module>event-sourcing</module>
+    <module>data-transfer-object</module>
+    <module>throttling</module>
+    <module>unit-of-work</module>
+    <module>partial-response</module>
+    <module>retry</module>
+    <module>dirty-flag</module>
+    <module>trampoline</module>
+    <module>ambassador</module>
+    <module>acyclic-visitor</module>
+    <module>collection-pipeline</module>
+    <module>master-worker</module>
+    <module>spatial-partition</module>
+    <module>commander</module>
+    <module>type-object</module>
+    <module>bytecode</module>
+    <module>leader-election</module>
+    <module>data-locality</module>
+    <module>subclass-sandbox</module>
+    <module>circuit-breaker</module>
+    <module>role-object</module>
+    <module>saga</module>
+    <module>double-buffer</module>
+    <module>sharding</module>
+    <module>game-loop</module>
+    <module>combinator</module>
+    <module>update-method</module>
+    <module>leader-followers</module>
+    <module>strangler</module>
+    <module>arrange-act-assert</module>
+    <module>transaction-script</module>
+    <module>registry</module>
+    <module>filterer</module>
+    <module>factory</module>
+    <module>separated-interface</module>
+    <module>special-case</module>
+    <module>parameter-object</module>
+    <module>active-object</module>
+    <module>model-view-viewmodel</module>
+    <module>composite-entity</module>
+    <module>table-module</module>
+    <module>presentation-model</module>
+    <module>lockable-object</module>
+    <module>fanout-fanin</module>
+    <module>domain-model</module>
+    <module>composite-view</module>
+    <module>metadata-mapping</module>
+    <module>service-to-worker</module>
+    <module>client-session</module>
+    <module>model-view-intent</module>
+    <module>currying</module>
+    <module>serialized-entity</module>
+    <module>identity-map</module>
+    <module>component</module>
+    <module>context-object</module>
+    <module>optimistic-offline-lock</module>
+    <module>curiously-recurring-template-pattern</module>
+    <module>microservices-log-aggregation</module>
+    <module>anti-corruption-layer</module>
+    <module>health-check</module>
+    <module>notification</module>
+    <module>single-table-inheritance</module>
+    <module>dynamic-proxy</module>
+    <module>gateway</module>
+    <module>serialized-lob</module>
+    <module>server-session</module>
+    <module>virtual-proxy</module>
+    <module>function-composition</module>
+    <module>microservices-distributed-tracing</module>
+    <module>microservices-idempotent-consumer</module>
+      <module>fallback</module>
+  </modules>
+  <repositories>
+    <repository>
+      <id>jitpack.io</id>
+      <url>https://jitpack.io</url>
+    </repository>
+  </repositories>
+  <dependencyManagement>
+    <dependencies>
+      <dependency>
+        <groupId>org.springframework.boot</groupId>
+        <artifactId>spring-boot-dependencies</artifactId>
+        <version>${spring-boot.version}</version>
+        <type>pom</type>
+        <scope>import</scope>
+      </dependency>
+      <dependency>
+        <groupId>commons-dbcp</groupId>
+        <artifactId>commons-dbcp</artifactId>
+        <version>${commons-dbcp.version}</version>
+      </dependency>
+      <dependency>
+        <groupId>org.htmlunit</groupId>
+        <artifactId>htmlunit</artifactId>
+        <version>${htmlunit.version}</version>
+      </dependency>
+      <dependency>
+        <groupId>com.google.code.gson</groupId>
+        <artifactId>gson</artifactId>
+        <version>${gson.version}</version>
+      </dependency>
+      <dependency>
+        <groupId>com.google.inject</groupId>
+        <artifactId>guice</artifactId>
+        <version>${guice.version}</version>
+      </dependency>
+      <dependency>
+        <groupId>com.github.stefanbirkner</groupId>
+        <artifactId>system-lambda</artifactId>
+        <version>${system-lambda.version}</version>
+        <scope>test</scope>
+      </dependency>
+    </dependencies>
+  </dependencyManagement>
+  <dependencies>
+    <dependency>
+      <groupId>org.slf4j</groupId>
+      <artifactId>slf4j-api</artifactId>
+      <version>${slf4j.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>ch.qos.logback</groupId>
+      <artifactId>logback-classic</artifactId>
+      <version>${logback.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>ch.qos.logback</groupId>
+      <artifactId>logback-core</artifactId>
+      <version>${logback.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.projectlombok</groupId>
+      <artifactId>lombok</artifactId>
+      <scope>provided</scope>
+    </dependency>
+  </dependencies>
+  <build>
+    <pluginManagement>
+      <plugins>
+        <plugin>
+          <groupId>org.apache.maven.plugins</groupId>
+          <artifactId>maven-compiler-plugin</artifactId>
+          <configuration>
+            <source>17</source>
+            <target>17</target>
+          </configuration>
+        </plugin>
+        <plugin>
+          <groupId>org.apache.maven.plugins</groupId>
+          <artifactId>maven-surefire-plugin</artifactId>
+          <version>${maven-surefire-plugin.version}</version>
+        </plugin>
+        <plugin>
+          <groupId>org.springframework.boot</groupId>
+          <artifactId>spring-boot-maven-plugin</artifactId>
+        </plugin>
+        <!-- Maven assembly plugin template for all child project to follow -->
+        <plugin>
+          <groupId>org.apache.maven.plugins</groupId>
+          <artifactId>maven-assembly-plugin</artifactId>
+          <executions>
+            <execution>
+              <phase>package</phase>
+              <goals>
+                <goal>single</goal>
+              </goals>
+              <configuration>
+                <descriptorRefs>
+                  <descriptorRef>jar-with-dependencies</descriptorRef>
+                </descriptorRefs>
+                <!-- below two line make sure the fat jar is sharing the same name as of project name -->
+                <finalName>${project.artifactId}-${project.version}</finalName>
+                <appendAssemblyId>false</appendAssemblyId>
+              </configuration>
+            </execution>
+          </executions>
+        </plugin>
+        <plugin>
+          <groupId>org.sonarsource.scanner.maven</groupId>
+          <artifactId>sonar-maven-plugin</artifactId>
+          <version>${sonar-maven-plugin.version}</version>
+        </plugin>
+      </plugins>
+    </pluginManagement>
+    <plugins>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-checkstyle-plugin</artifactId>
+        <version>${maven-checkstyle-plugin.version}</version>
+        <executions>
+          <execution>
+            <id>validate</id>
+            <goals>
+              <goal>check</goal>
+            </goals>
+            <phase>validate</phase>
+            <configuration>
+              <configLocation>google_checks.xml</configLocation>
+              <suppressionsLocation>checkstyle-suppressions.xml</suppressionsLocation>
+
+              <failOnViolation>true</failOnViolation>
+              <violationSeverity>warning</violationSeverity>
+              <includeTestSourceDirectory>false</includeTestSourceDirectory>
+            </configuration>
+          </execution>
+        </executions>
+      </plugin>
+      <plugin>
+        <groupId>com.mycila</groupId>
+        <artifactId>license-maven-plugin</artifactId>
+        <version>${license-maven-plugin.version}</version>
+        <configuration>
+          <licenseSets>
+            <licenseSet>
+              <multi>
+                <preamble><![CDATA[This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).]]></preamble>
+                <header>com/mycila/maven/plugin/license/templates/MIT.txt</header>
+              </multi>
+              <excludes>
+                <exclude>**/README</exclude>
+                <exclude>src/test/resources/**</exclude>
+                <exclude>src/main/resources/**</exclude>
+                <exclude>checkstyle-suppressions.xml</exclude>
+              </excludes>
+            </licenseSet>
+          </licenseSets>
+          <properties>
+            <owner>Ilkka Seppälä</owner>
+            <email>iluwatar@gmail.com</email>
+          </properties>
+        </configuration>
+        <executions>
+          <execution>
+            <id>install-format</id>
+            <phase>install</phase>
+            <goals>
+              <goal>format</goal>
+            </goals>
+          </execution>
+        </executions>
+      </plugin>
+      <plugin>
+        <groupId>org.jacoco</groupId>
+        <artifactId>jacoco-maven-plugin</artifactId>
+        <version>${jacoco.version}</version>
+        <executions>
+          <execution>
+            <id>prepare-agent</id>
+            <goals>
+              <goal>prepare-agent</goal>
+            </goals>
+          </execution>
+          <execution>
+            <id>report</id>
+            <goals>
+              <goal>report</goal>
+            </goals>
+          </execution>
+        </executions>
+      </plugin>
+      <plugin>
+        <groupId>com.iluwatar.urm</groupId>
+        <artifactId>urm-maven-plugin</artifactId>
+        <version>${urm-maven-plugin.version}</version>
+        <configuration>
+          <!-- if outputDirectory is not set explicitly it will default to your build dir -->
+          <outputDirectory>${project.basedir}/etc</outputDirectory>
+          <packages>
+            <param>com.iluwatar</param>
+          </packages>
+          <includeMainDirectory>true</includeMainDirectory>
+          <includeTestDirectory>false</includeTestDirectory>
+          <presenter>plantuml</presenter>
+        </configuration>
+        <executions>
+          <execution>
+            <phase>process-classes</phase>
+            <goals>
+              <goal>map</goal>
+            </goals>
+          </execution>
+        </executions>
+      </plugin>
+    </plugins>
+  </build>
+</project>