Skip to main content
All posts

Mar 8, 2026 · Alejandro Santana · Architecture · AWS · Patterns

A practical serverless architecture playbook for AWS

The defaults we examine first for events, idempotency, data, observability, and safe delivery.

Good serverless architecture is less about collecting services and more about making ownership and failure behavior explicit.

These are the defaults we examine first. They are starting points, not rules that override workload context.

Draw the event path before the resource diagram

Start with what happens to one request, command, or event. Name the producer, the durable boundary, every consumer, and the final state change.

The resource diagram becomes much easier after the team agrees on the event path. It also exposes unclear ownership early.

Use an event bus for facts, a queue for work

EventBridge is a strong fit when a producer emits a fact and multiple consumers may respond independently. SQS is a strong fit when a consumer owns a unit of work and needs buffering, retry, and backpressure.

Many systems use both: route a domain event through EventBridge, then deliver work to an SQS queue owned by each asynchronous consumer.

Make handlers idempotent

Lambda can retry. SQS can redeliver. Event-driven systems should assume the same input may arrive more than once.

Choose an idempotency key from the business operation, store the result of the first successful attempt, and return that result for duplicates. Do not rely on the event source to provide exactly-once business behavior.

Put retry ownership in one place

A failure becomes difficult to reason about when the SDK, function, queue, and workflow all retry independently.

Decide which layer owns retry for each interaction. Use bounded attempts, backoff appropriate to the dependency, and a terminal path that an operator can inspect. For asynchronous work, that often means a dead-letter queue or a failure destination with enough context to replay safely.

Model DynamoDB from access patterns

Begin with the reads and writes the application must support, not a list of entities. A single-table design can work well when access patterns are stable and related records need efficient retrieval.

Split tables when ownership, scaling, backup, encryption, or access patterns make the separation valuable. “One table” is not the objective; predictable operations are.

Treat observability as part of the interface

Every function should emit structured logs with a correlation identifier. Key workflows need metrics for volume, error rate, latency, throttling, and backlog. Traces are most useful when the team already knows which question they need to answer.

Create alarms for user or business impact, not for every metric that can move.

Deliver small, reversible changes

Infrastructure as code should make the deployment reviewable. Prefer changes that can be deployed and validated independently. Use aliases, weighted routing, feature flags, or parallel event consumers when they reduce cutover risk.

For each deployment, know the rollback boundary. A code rollback is simple; a data-shape change or emitted event may not be.

Review the defaults against the workload

The playbook is a checklist for questions:

  • Where is the durable boundary?
  • Who owns retry and replay?
  • What makes the operation idempotent?
  • Which metric shows customer impact?
  • What can be rolled back independently?

If the architecture answers those questions clearly, the AWS services usually become the easier part of the decision.