Why this matters
- VaultCommerce payment authorization needs a synchronous response within 3 seconds — async would break the checkout UX.
- Email receipts and search index updates tolerate seconds of delay; forcing them into the critical path wasted SLA budget.
- Cascading failures propagate through sync call graphs; async boundaries contain blast radius to one consumer group.
- Senior interviews ask you to classify each VaultCommerce integration as sync or async and defend the choice.
Latency budgets and critical paths
VaultCommerce allocates a 2.5s end-to-end checkout budget. Payment gateway (sync, 1.2s), fraud pre-check (sync, 400ms), and order persistence (sync, 200ms) consume the path. Everything else — warehouse notification, CRM sync, recommendation refresh — publishes to Kafka after commit.
Key points
- Critical path — user-visible operations that must complete before showing success
- Fire-and-forget — publish without waiting for consumer processing (still wait for broker ack)
- Temporal coupling — caller blocked until callee finishes
- Eventual consistency — all replicas converge given enough time without simultaneous reads
- Compensating action — async saga step that undoes a prior effect on failure
Coupling dimensions
Temporal coupling: sync callers wait. Spatial coupling: callers need endpoint URLs and compatible schemas at call time. Async removes spatial coupling via topic contracts and temporal coupling via the log buffer. You still couple on schema evolution — a breaking change to OrderPlaced breaks all consumers.
Failure semantics differ
A sync timeout is ambiguous: did payment succeed? VaultCommerce returns 503 and lets the client retry with idempotency keys. An async consumer failure retries from the last committed offset — the order API already returned 201. Operators watch consumer lag, not HTTP error rates, for those paths.
// VaultCommerce — sync payment inside transaction boundary, async side effects after
@Transactional
public OrderConfirmation checkout(CheckoutRequest req) {
Order order = orderRepo.save(Order.from(req));
PaymentResult payment = paymentGateway.authorizeSync(req.payment()); // sync, bounded timeout
order.markPaid(payment.transactionId());
// After commit, outbox relay publishes OrderPlaced — not in this thread's critical path
outbox.enqueue(new OutboxMessage("vaultcommerce.orders.placed.v1", order.getId(), order.toEvent()));
return OrderConfirmation.of(order);
}
Quick recall
Everything you need if you only revisit this box.
- Sync for user-facing decisions; async for side effects and scale.
- Async trades immediate consistency for isolation and throughput.
- Schema contracts couple async systems as much as REST APIs do.
Test yourself
Answer these before moving on — recall is what makes it stick.