Fast APIs That Fail Are Still Bad APIs: Resilience and Fallback Strategies

📘 Part 6: Fast APIs That Fail Are Still Bad APIs So far,I improved API performance using async calls 🚀 But here’s the uncomfortable truth: 👉 Speed without resilience is dangerous. If one service fails or slows down, your entire API can collapse. Let’s fix that. 🧠 Real Failure Scenarios You’re calling: Product service Price service Inventory service What can go wrong? ❌ One service throws an exception ❌ One service is too slow ❌ One returns bad/null data 👉 Goal: Return the best possible response, not a failure by default 🚀 Step 1: Add Timeout + Fallback CompletableFuture<Product> productFuture = CompletableFuture.supplyAsync(() -> productService.findById(id), executor) .completeOnTimeout(getDefaultProduct(id), 2, TimeUnit.SECONDS) .exceptionally(ex -> { log.error("Product failed", ex); return getDefaultProduct(id); }); ✔ Timeout handled ✔ Exception handled ✔ Always returns something 🧩 Repeat for Other Services Apply the same pattern for price and inventory. 👉 Now your API doesn’t crash when one dependency misbehaves. 🔗 Step 2: Combine Safely CompletableFuture.allOf(productFuture, priceFuture, inventoryFuture).join(); Product product = productFuture.join(); Price price = priceFuture.join(); Inventory inventory = inventoryFuture.join(); ✔ No failure propagation ✔ Controlled aggregation ⚠️ Cleaner Alternative: handle() CompletableFuture<Product> productFuture = CompletableFuture.supplyAsync(() -> productService.findById(id), executor) .handle((res, ex) -> ex != null ? getDefaultProduct(id) : res); // res = result of the async computation (if successful) // ex = exception (if something went wrong) 👉 One place for both success + failure 🧠 Step 3: Define What’s Critical Not all services are equal. Example: Product → Critical Price → Optional Inventory → Optional if (product.getName().equals("Unknown")) { throw new RuntimeException("Critical service failed"); } // "UNKNOWN" means: “We couldn’t fetch real data, so we’re returning a safe default.” 👉 Fail only when it actually matters 🔥 Step 4: Use Custom Thread Pool Default thread pools are not your friend in production. @Bean public Executor taskExecutor() { return Executors.newFixedThreadPool(10); } ✔ Predictable performance ✔ Better control under load 🧠 Production Upgrade For real systems, go beyond basic handling: Use tools like: Resilience4j They provide: ✔ Circuit breakers ✔ Retries ✔ Bulkheads ✔ Rate limiting 🎯 What You Achieve Service fails → fallback response Service slow → timeout fallback Critical failure → controlled API error 💡 Core Insight 👉 Async improves speed 👉 Resilience ensures survival You need both. Always. ✅ Final Takeaway A production-ready async API must include: Timeouts Exception handling Fallback strategies Thread pool control (Advanced) resilience patterns #Java #SpringBoot #BackendEngineering #Microservices #SystemDesign #Resilience #PerformanceOptimization

🚀 Improving API Performance using Multi-Threading in Spring Boot In today’s fast-paced systems, API latency directly impacts user experience and business revenue. I recently built a small project to understand how synchronous vs asynchronous processing affects performance in a microservices-like setup. 🔍 Use Case A service needs to fetch: * Product details * Price * Inventory from different sources (simulated as separate services). --- ❌ Problem with Synchronous Approach All calls run in a single thread: * Product → Price → Inventory * Each call waits for the previous one * Total time ≈ 6+ seconds (due to delays) --- ✅ Solution: Asynchronous with Multi-Threading Using Java’s CompletableFuture, we run all calls in parallel: * Product → Thread 1 * Price → Thread 2 * Inventory → Thread 3 ⏱ Result: Total time reduced to ~2 seconds --- 💡 Key Learning * Don’t block a single thread for independent tasks * Use parallel execution for IO-bound operations * `CompletableFuture` is a simple and powerful way to achieve concurrency in Spring Boot --- 📊 Performance Comparison * Sync: ~6.7s * Async: ~2.1s --- 📌 Takeaway Whenever your API aggregates data from multiple services, go async to reduce latency and improve scalability --- I’ll be sharing: 👉 Code breakdown 👉 Interview questions from this concept 👉 Real-world improvements (thread pools, error handling) Stay tuned 🔥 #Java #SpringBoot #BackendDevelopment #Microservices #Multithreading #Performance #APIDesign

To view or add a comment, sign in

Explore content categories