Skip to content

Revision · Communication & APIs

This part mapped the whole landscape of service-to-service communication onto one question — does the caller wait for the answer, or not? Every protocol and pattern below is a point on that synchronous-versus-asynchronous axis, chosen by paying the right cost on purpose.

  • The sync/async axis — the single organizing question is whether the caller blocks for a reply; synchronous buys simplicity at the cost of coupling, asynchronous buys resilience and decoupling at the cost of complexity.
  • REST APIs — the web’s default: resources plus a fixed set of verbs, statelessness, status codes, versioning, and pagination — simple and universal, but it strains on chatty graphs and over/under-fetching.
  • RPC & gRPC — make a remote call feel like a local function, with protobuf schemas, HTTP/2 transport, and four streaming shapes; it wins for typed, fast, internal calls but costs you human-readability and browser reach.
  • GraphQL — let the client specify exactly what it needs to kill over- and under-fetching, paid for with resolver complexity, the N+1 problem, and harder caching than REST.
  • Synchronous vs asynchronous messaging — temporal coupling is the heart of it: waiting ties the caller’s fate to the callee, so going async trades immediate latency for resilience when the other side is down.
  • Real-time: polling, WebSockets & SSE — pushing data toward clients along a ladder from short and long polling to bidirectional WebSockets and one-way SSE, chosen by direction and scale.
  • Event-driven architecture — build around facts that happened (events) rather than commands, using pub/sub, choreography vs orchestration, and event sourcing — with the dual-write problem lurking underneath.

The skill is not memorizing acronyms but knowing where to wait and where not to. Most production systems blend both styles: a synchronous edge for the user-facing request and an asynchronous spine for everything that can happen later, because the right cost to pay differs per interaction, not per system. That decision of what to wait for leads straight into the next part — the distributed-systems theory that explains why waiting, retrying, and ordering are so fraught in the first place.