Skip to content
AITroveRead. Build. Understand.
Make this comfortable

Java applyToEither: use the first normal result of two stages

Last updated: 4 Oct 20265 min read
tutorial
AdvancedBy AITrove Editorial

CompletableFuture.applyToEither applies a function when either input completes normally. It is a result race, not automatic hedging, timeout, or loser cancellation.

Operational contract

Two already-started replica lookups can feed this method. It rejects null results in the winning callback, then returns the first normal value that reaches that callback. Exceptional completion rules should be tested for the application's failure combinations; do not assume the other request always rescues an early failure. A service that needs guaranteed first-success behavior across failures should coordinate those results explicitly. Both replica requests can still consume bandwidth after one result is chosen.

Failure case

The east replica responds normally while the west request is still blocked. The returned future can complete from east, but west remains active unless its caller cancels or times it out. An early failure must be handled under an explicit fallback policy rather than presumed harmless.

Java code

Java
import java.util.Objects;
import java.util.concurrent.CompletableFuture;

public class ReplicaReceiptRace {
    public static CompletableFuture<String> firstReceipt(
            CompletableFuture<String> eastReplica,
            CompletableFuture<String> westReplica) {
        Objects.requireNonNull(eastReplica);
        Objects.requireNonNull(westReplica);
        return eastReplica.applyToEither(westReplica, receipt ->
                Objects.requireNonNull(receipt, "Replica returned no receipt"));
    }
}

Performance and ownership cost

The continuation adds O(1) bookkeeping. Starting two requests can nearly double upstream resource use, even when one wins quickly; latency follows completion timing and failure handling, not a fixed bound.

Common Mistakes

  • Do not assume the losing request is cancelled.
  • Do not describe this stage as a guaranteed first-success fallback for every failure order.
  • Do not launch duplicate writes through a result race without idempotency rules.

Connected lessons

java
race and recovery
completablefuture-applytoeither-race
Storage details