advanced~2h

End-to-End Example: A Serverless Web Application

Combining API Gateway, Lambda, DynamoDB, Cognito, and S3/CloudFront into a complete serverless architecture — no servers to manage at any layer.

Want a visual for this topic?

Generate a diagram tailored to End-to-End Example: A Serverless Web Application — the AI picks whichever visual (architecture, flowchart, ER diagram, etc.) best fits this specific AWS concept.

Sign in to generate a visual →
0
Subtopics

🎓 Learning objectives

  • Trace a user request through a complete serverless architecture end to end
  • Explain why this architecture has genuinely zero idle-server cost, unlike the EC2-based reference architecture
  • Compare this serverless architecture's tradeoffs against the EC2-based scalable web app example

What is it?

This is a complete, worked serverless architecture combining API Gateway, Lambda, DynamoDB, Cognito, and S3/CloudFront — an alternative to the EC2-based reference architecture where no layer requires provisioning or managing any server at all, scaling automatically from zero to high traffic and back.

Why it exists

Not every application needs (or benefits from) the EC2-based architecture's always-on compute and database capacity — many applications, especially those with genuinely unpredictable or intermittent traffic, are better served by an architecture that scales all the way down to zero cost during idle periods and up automatically during traffic, with no capacity planning required at any layer. This example exists to show that alternative pattern concretely, end to end.

Problem it solves

It solves the idle-capacity-cost problem across the entire stack, not just compute (Lambda, DynamoDB On-Demand, and API Gateway all scale to zero cost when idle, unlike EC2/RDS's always-running minimum footprint), the operational-overhead problem (no servers to patch, no capacity to plan, at any layer), and the authentication-from-scratch problem (Cognito handles user sign-up/sign-in without building custom auth infrastructure).

Intuition

The EC2-based reference architecture is like owning and staffing a physical restaurant that has fixed costs (rent, staff wages) whether customers show up or not. This serverless architecture is like a fully on-demand catering service that only costs money exactly when someone books an event, scaling from zero to a huge event with no fixed overhead in between — genuinely different economics, well suited to unpredictable, intermittent demand.

Analogy

A ride-sharing service (pay exactly for the trips taken, zero cost when no one's riding) versus owning a fleet of company cars with drivers on salary (fixed cost regardless of actual usage) — the serverless architecture is the ride-sharing model applied to infrastructure, appropriate when usage is genuinely variable or unpredictable, where the always-on model's fixed cost would otherwise be wasted during idle periods.

Technical explanation

The frontend (a single-page application's static build) is hosted in S3 and served through CloudFront for global edge caching and HTTPS. User authentication runs through a Cognito User Pool, issuing JWTs on successful sign-in. API calls go to API Gateway (HTTP API type, for lower cost/latency), protected by a JWT authorizer validating the Cognito-issued token before any request reaches business logic. Each API route maps to a Lambda function (via Lambda Proxy integration) implementing that specific piece of business logic, reading and writing to DynamoDB (using On-Demand capacity mode to avoid any capacity planning) as its data store. For any user file uploads, the pattern from the EC2-based example still applies — Lambda generates a pre-signed S3 URL rather than proxying file bytes through itself, since Lambda's payload size limits make it a poor fit for large file transfer.

Architecture

The complete architecture: S3 (static frontend hosting) + CloudFront (CDN, HTTPS, edge caching) → Cognito User Pool (authentication, issuing JWTs) → API Gateway HTTP API (routing, JWT authorization via Cognito) → Lambda functions (one or more, implementing business logic) → DynamoDB (On-Demand capacity, the application's primary data store) → S3 (separate bucket or prefix for user-uploaded files, accessed via pre-signed URLs) → CloudWatch (Lambda function logs and metrics, alarms on error rate/duration).

Workflow

  1. Build and deploy the frontend's static assets to S3, fronted by CloudFront. 2) Set up a Cognito User Pool for authentication, integrating sign-up/sign-in into the frontend. 3) Design the DynamoDB table's primary key structure around the application's actual access patterns (the single most important DynamoDB design decision, done upfront). 4) Build Lambda functions implementing each piece of business logic, each scoped with a least-privilege IAM execution role. 5) Wire these functions to API Gateway routes, protected by a JWT authorizer validating Cognito tokens. 6) Set up CloudWatch alarms on Lambda error rates and API Gateway 5xx responses for operational visibility.

Example

A note-taking application's entire backend runs on this pattern: users sign in via Cognito (including Google federated sign-in), the React frontend is served globally from S3/CloudFront, creating/editing/deleting notes calls Lambda functions through API Gateway (each function scoped to exactly the DynamoDB operations it needs via IAM), and notes are stored in DynamoDB with the user's Cognito identity ID as the partition key (ensuring one user's notes are naturally isolated from another's by the data model itself). During a period with zero active users, the entire backend costs essentially nothing beyond negligible storage; during a traffic spike from a product mention going viral, Lambda and DynamoDB On-Demand scale automatically with no capacity planning or manual intervention needed.

Real-world usage

This exact pattern (S3/CloudFront frontend, Cognito auth, API Gateway + Lambda backend, DynamoDB data store) is AWS's own standard serverless web application reference architecture, extensively documented in AWS's serverless application guidance and commonly used for startups and applications with genuinely variable, hard-to-predict traffic where the always-on EC2-based architecture's fixed cost would be wasteful.

Trade-offs

This architecture trades some latency predictability (cold starts) and relational query flexibility (DynamoDB's key-based model) for genuinely zero idle cost and zero server management — the right choice for applications with variable, unpredictable, or currently-unproven traffic. The EC2-based reference architecture trades a real baseline cost and more operational surface for more predictable latency and more flexible relational querying — better suited to established, high-volume, predictable-traffic applications, especially ones needing complex relational queries DynamoDB doesn't handle well.

Visual explanation

Picture a user's browser loading a single-page application's static assets (HTML/CSS/JS) from S3 via CloudFront. The user signs in through Cognito, receiving JWTs. The app calls an API Gateway endpoint with those tokens, which validates them via a Cognito authorizer before invoking the appropriate Lambda function. That Lambda function reads/writes application data in DynamoDB and returns a response, all the way back through API Gateway to the browser — at no point in this entire chain is there a server that was provisioned ahead of time and sits idle waiting for requests.

Advantages

  • Genuinely zero idle cost across the entire stack — no minimum server footprint at any layer, unlike the EC2-based architecture's always-running minimum instances

  • Scales automatically from zero to very high traffic with no manual capacity planning at any layer

  • No servers to patch or manage at any point in the architecture, meaningfully lower operational burden

  • Cognito eliminates the need to build authentication infrastructure from scratch

Disadvantages

  • Lambda cold starts can add latency variability that the EC2-based architecture's always-warm instances don't have

  • DynamoDB's key-based access model requires knowing your access patterns upfront, less flexible than RDS's ad-hoc relational querying for evolving requirements

  • At very high, sustained, constant traffic, this architecture's per-invocation/per-request pricing can become more expensive than the EC2-based architecture's flat-rate capacity, the opposite of its advantage at low/variable traffic

  • Debugging and locally testing a fully serverless, distributed architecture has real tooling and workflow differences from a traditional server-based application

Common mistakes

  • Choosing this architecture for a workload that's actually a poor fit for DynamoDB's access-pattern-driven data model, fighting the tool instead of recognizing RDS/Aurora would serve the actual query needs better

  • Not accounting for Lambda cold-start latency in a genuinely latency-critical, synchronous user-facing path where it would be noticeable and problematic

  • Designing the DynamoDB table's primary key without fully thinking through the application's actual access patterns upfront, requiring a difficult redesign later

  • Granting overly broad IAM execution role permissions to Lambda functions instead of scoping each function tightly to exactly what it needs

  • Assuming this architecture is automatically cheaper than the EC2-based alternative at every scale, without recognizing that very high, sustained traffic can flip that cost comparison the other way

🎤 Interview questions

Walk through this serverless architecture end to end, tracing a single authenticated API request. (Listen for: a clear, ordered trace through CloudFront/S3 for the frontend, Cognito for auth/JWT issuance, API Gateway's JWT authorizer validating the token, Lambda executing business logic, DynamoDB for data access.)

Why does this architecture have genuinely zero idle cost, unlike the EC2-based reference architecture? (Listen for: every layer — Lambda, API Gateway, DynamoDB On-Demand — bills per-use with no minimum always-running footprint, unlike EC2/RDS's minimum instance count that runs (and costs) continuously regardless of traffic.)

When would you choose this serverless architecture over the EC2-based one, and vice versa? (Listen for: serverless for variable/unpredictable/low traffic and minimal operational burden; EC2-based for predictable high-volume traffic, complex relational query needs, or latency-critical paths sensitive to cold starts.)

How does Cognito fit into this architecture, and what would be missing without it? (Listen for: handles user sign-up/sign-in and issues JWTs validated by API Gateway; without it, the team would need to build and secure custom authentication infrastructure from scratch.)

What's a real risk of choosing DynamoDB for this architecture's data store without fully designing around actual access patterns first? (Listen for: DynamoDB's performance and query capability depend entirely on the primary key design matching real access patterns; a poor upfront design can require a difficult redesign or force inefficient workarounds later.)

💬 Deep Dive with AI

Related concepts

end-to-end-scalable-web-applambda-serverlesscognito-identity

Next Step

Continue to Applying the Well-Architected Framework: A Worked Example