System Architecture

Event-Driven vs Request-Response Architecture

Event-driven and request-response are foundational communication patterns that shape how services interact across your system. The right choice depends on whether your operations are inherently synchronous (a user expecting an immediate result) or asynchronous (background work that can proceed independently of the caller), and how tightly your services should be coupled.

Halkwinds VerdictRequest-response is the natural pattern for synchronous, user-facing interactions where the caller needs an immediate result — REST APIs, GraphQL queries, and RPC calls. Event-driven architecture enables loose coupling, resilience, and high-throughput asynchronous processing, making it the preferred pattern for workflows, integrations, real-time data pipelines, and any operation where the producer should not wait for downstream completion.
Option A

Event-Driven

Asynchronous, decoupled communication through events and message brokers

Typical Cost

Managed brokers: AWS SQS ($0.40 per million messages), AWS EventBridge ($1 per million events), AWS MSK (Kafka) from $0.21/hour per broker. Kafka on Kubernetes requires platform engineering investment.

Timeline

Basic producer/consumer with SQS or EventBridge: 1–3 days. Full event-driven workflow with saga orchestration, dead-letter queues, and distributed tracing: 3–8 weeks.

Pros

Temporal decoupling — producers and consumers operate independently; the producer does not wait for downstream processing to complete
High resilience — events are persisted in the broker (Kafka, SQS, EventBridge), so consumers can fail and recover without data loss
Natural horizontal scaling of consumers independent of producers
Enables complex workflows and sagas across multiple services without tight point-to-point coupling
Supports multiple independent consumers processing the same event for different purposes (fan-out, audit, analytics)

Cons

Debugging and tracing are harder — distributed correlation IDs and event replay are required to understand system behavior
No immediate feedback to the original caller; implementing request-reply patterns over async messaging adds complexity
Eventual consistency — downstream state may lag behind the originating event, requiring careful design for time-sensitive reads
Broker infrastructure (Kafka, RabbitMQ, AWS MSK) adds operational complexity, cost, and an additional failure domain
Error handling and compensating transactions (saga pattern) for failed events require explicit design effort
Option B

Request-Response

Synchronous, direct communication where callers receive immediate results

Typical Cost

Minimal additional infrastructure cost beyond the services themselves. API Gateways (AWS API Gateway, Kong) add $3.50 per million API calls on AWS. REST/gRPC services run on existing container or serverless infrastructure.

Timeline

REST API with OpenAPI spec: 1–5 days per service. gRPC service with client/server code generation: 2–7 days. Full API gateway integration with auth, rate limiting, and monitoring: 1–3 weeks.

Pros

Simple, intuitive programming model — call a service, get a result; no async machinery required
Immediate feedback enables rich user experiences where the UI updates directly from the API response
Strong consistency — the caller receives the state of the system at the time of the call
Extensive tooling for REST (OpenAPI, Postman, Swagger) and gRPC makes design, testing, and documentation straightforward
Easier to debug — a single request-response trace captures the entire interaction in a single log stream

Cons

Temporal coupling — if the downstream service is unavailable or slow, the caller blocks and may time out
Cascading failures are more likely — a slow dependency propagates latency up the call chain to the end user
Harder to scale independently — adding consumers requires routing changes or load balancer reconfiguration
Not well-suited for fan-out operations; notifying 10 downstream services synchronously creates a serial bottleneck
Long-running operations (minutes or longer) are awkward to model in synchronous HTTP without polling or webhook callbacks

Side-by-Side

Detailed Comparison

DimensionEvent-DrivenRequest-ResponseWinner
CouplingLoose — producers and consumers are independent; changes to one do not require changes to the otherTight — caller and callee must agree on API contract; version changes require coordinationEvent-Driven
Consistency ModelEventual — consumers may process events with a lag; state reflects past events, not the present momentStrong — caller receives the current state of the system at call timeRequest-Response
Resilience to FailuresHigh — events persist in the broker; consumers recover after failure without data lossLower — caller blocks on downstream availability; cascading failures propagate synchronouslyEvent-Driven
Debugging & ObservabilityComplex — requires distributed tracing (OpenTelemetry, Jaeger) and correlation IDs across async boundariesStraightforward — single request trace captures the full interactionRequest-Response
Latency for End UserNot applicable to synchronous user interactions; adds processing delay for background workflowsImmediate response — optimal for user-facing operations requiring sub-second feedbackRequest-Response
Throughput & ScalabilityConsumers scale independently; brokers absorb bursts without back-pressure on producersCaller blocks until response; scaling requires adding instances behind a load balancerEvent-Driven
Fan-OutNatural — one event can be consumed by many independent subscribers simultaneouslyAwkward — sequential synchronous calls to multiple services create serial latencyEvent-Driven
Error HandlingDead-letter queues, retry policies, and compensating transactions handle failures asynchronouslyImmediate error response allows caller to handle failures synchronously and give user feedbackRequest-Response
Implementation ComplexityHigher — broker infrastructure, idempotency, ordering guarantees, and saga patterns add design complexityLower — well-understood HTTP/gRPC patterns with extensive framework supportRequest-Response
Long-Running OperationsIdeal — fire-and-forget events trigger workflows that can run for hours without blocking callersPoor fit — synchronous HTTP connections time out; requires polling or webhook callbacks for long jobsEvent-Driven

Decision Framework

When to Choose Each Option

Choose Event-Driven when...

  • Your operation involves multiple downstream services that should react to a state change independently and asynchronously
  • You are implementing a multi-step business workflow where individual steps can fail and retry without rolling back the entire process
  • You need to scale consumers independently of producers to handle variable processing loads
  • Your use case involves real-time data streaming, analytics ingestion, or continuous event processing
  • You want to decouple service teams so that adding a new consumer does not require changes to the producing service

Choose Request-Response when...

  • The end user or calling service needs an immediate, deterministic result to proceed — a login response, a search result, a form submission confirmation
  • Your operation requires reading strongly consistent state that must reflect the absolute latest data
  • The interaction is simple and point-to-point; the overhead of a message broker adds cost and complexity without benefit
  • You need rich, structured error responses that the caller can act on in real time (validation errors, authorization failures)
  • Your team is earlier in their distributed systems journey and needs a simpler programming model to maintain velocity

Not sure which is right for your project?

Use request-response for user-facing APIs, authentication flows, search queries, and any interaction requiring an immediate, consistent result. Use event-driven architecture for order processing workflows, notification pipelines, audit logging, data synchronization across services, and any multi-step process where individual steps can execute independently and failures should not cascade synchronously to the end user.

Common Questions

Frequently Asked Questions

Yes, and they almost always should. Well-designed distributed systems use request-response for synchronous user interactions (APIs, queries) and event-driven patterns for background processing, cross-service workflows, and integrations. An e-commerce checkout might use a synchronous REST API to confirm the order to the user, then immediately publish an OrderPlaced event that triggers inventory reservation, payment capture, and fulfillment workflows asynchronously.

Work With Halkwinds

Ready to Make the Right Decision?

A 30-minute scoping call is enough to recommend the right approach for your specific context, budget, and timeline.

Browse All Comparisons