Real World Example

Travel Search Aggregator (MakeMyTrip style)

A flight search page queries several airlines at once, waits at most a fixed time, ignores airlines that fail or time out, and shows the cheapest fares. This is a classic CompletableFuture fan-out / fan-in.

Example

import java.util.*;
import java.util.concurrent.*;

public class Main {
    record Fare(String airline, int price) {}

    static Fare query(String airline, int delayMs, int price) {
        try { Thread.sleep(delayMs); } catch (InterruptedException e) { throw new RuntimeException(e); }
        if (price < 0) throw new IllegalStateException(airline + " API error");
        return new Fare(airline, price);
    }

    public static void main(String[] args) {
        try (ExecutorService io = Executors.newFixedThreadPool(5)) {
            Map<String, CompletableFuture<Optional<Fare>>> calls = new LinkedHashMap<>();
            calls.put("IndiGo", call(io, "IndiGo", 100, 4899));
            calls.put("Air India", call(io, "Air India", 150, 5600));
            calls.put("Akasa", call(io, "Akasa", 80, 4650));
            calls.put("SpiceJet", call(io, "SpiceJet", 50, -1));        // fails
            calls.put("Vistara", call(io, "Vistara", 3000, 4300));      // too slow

            CompletableFuture.allOf(calls.values().toArray(new CompletableFuture[0])).join();

            calls.forEach((name, f) -> System.out.println(name + ": " +
                    f.join().map(fare -> "Rs " + fare.price()).orElse("unavailable")));

            List<Fare> sorted = calls.values().stream().map(CompletableFuture::join)
                    .flatMap(Optional::stream).sorted(Comparator.comparingInt(Fare::price)).toList();
            System.out.println("Cheapest: " + sorted.get(0));
        }
    }

    static CompletableFuture<Optional<Fare>> call(ExecutorService io, String airline, int delay, int price) {
        return CompletableFuture.supplyAsync(() -> Optional.of(query(airline, delay, price)), io)
                .completeOnTimeout(Optional.empty(), 500, TimeUnit.MILLISECONDS)
                .exceptionally(ex -> Optional.empty());
    }
}

Output

IndiGo: Rs 4899
Air India: Rs 5600
Akasa: Rs 4650
SpiceJet: unavailable
Vistara: unavailable
Cheapest: Fare[airline=Akasa, price=4650]

Production Notes

  • Use a dedicated, bounded executor per downstream system so one slow airline cannot eat all threads (bulkhead pattern).
  • Log failures inside exceptionally; return a fallback instead of failing the whole page.
  • In Java 21 a virtual-thread executor makes this simpler: write blocking calls, run thousands at once.