Skip to content

Serverless – Lambda, DynamoDB, API Gateway, Cognito

Serverless is a paradigm in which developers no longer have to manage servers. They just deploy code — more precisely, they just deploy functions.

Initially, serverless meant FaaS (Function as a Service). The idea was pioneered by AWS Lambda, but the label has since widened to cover anything managed: databases, messaging, storage and so on.

The deck’s list of what counts as serverless on AWS:

  • AWS Lambda
  • DynamoDB
  • AWS Cognito
  • AWS API Gateway
  • Amazon S3
  • AWS SNS & SQS
  • AWS Kinesis Data Firehose
  • Aurora Serverless
  • Step Functions
  • Fargate

Put together, they form the canonical serverless web application: an S3 bucket serves static content, Cognito handles log in, API Gateway exposes the REST API, Lambda runs the logic, and DynamoDB stores the data. No instance is involved anywhere in that chain.

The clearest way to understand Lambda is by contrast with EC2.

Amazon EC2 AWS Lambda
Virtual servers in the cloud Virtual functions — no servers to manage
Limited by RAM and CPU Limited by time — short executions
Continuously running Runs on demand
Scaling means intervention to add or remove servers Scaling is automated
  • Easy pricing: you pay per request and per compute time, with a free tier of 1,000,000 requests and 400,000 GB-seconds of compute time.
  • Integrated with the whole AWS suite of services.
  • Integrated with many programming languages.
  • Easy monitoring through AWS CloudWatch.
  • Easy to get more resources per function — up to 10 GB of RAM.
  • Crucially, increasing RAM also improves CPU and network performance. Memory is the single dial you turn.

Lambda supports Node.js (JavaScript), Python, Java, C# (.NET Core) and PowerShell, and Ruby. Beyond that there is the Custom Runtime API, community supported, used for languages such as Rust or Golang.

Lambda can also run a container image, but with a condition: the container image must implement the Lambda Runtime API.

The main services that trigger or work with Lambda are API Gateway, Kinesis, DynamoDB, S3, CloudFront, CloudWatch Events / EventBridge, CloudWatch Logs, SNS, SQS and Cognito.

Two example architectures make the pattern concrete:

  • Serverless thumbnail creation: a new image lands in S3, which triggers a Lambda function; the function creates a thumbnail and pushes it back to S3, and pushes metadata (image name, image size, creation date and so on) into DynamoDB.
  • Serverless CRON job: a CloudWatch Events / EventBridge rule triggers a Lambda function every hour to perform a task, with no instance sitting idle between runs.

The pricing page is at https://aws.amazon.com/lambda/pricing/. The structure has two parts.

Pay per call: the first 1,000,000 requests are free, then $0.20 per 1 million requests ($0.0000002 per request).

Pay per duration, billed in increments of 1 ms: 400,000 GB-seconds of compute time per month for free, which is 400,000 seconds if the function has 1 GB of RAM, or 3,200,000 seconds at 128 MB. After that it costs $1.00 for 600,000 GB-seconds.

It is usually very cheap to run Lambda, which is a large part of why it is so popular.

These limits are per region, and the exam does test them.

Execution limits:

  • Memory allocation: 128 MB to 10 GB, in 1 MB increments.
  • Maximum execution time: 900 seconds (15 minutes).
  • Environment variables: 4 KB.
  • Disk capacity in the function container (/tmp): 512 MB to 10 GB.
  • Concurrent executions: 1000 — this one can be increased.

Deployment limits:

  • Deployment package size (compressed .zip): 50 MB.
  • Uncompressed deployment size (code plus dependencies): 250 MB.
  • You can use the /tmp directory to load other files at startup, which is the escape hatch when the package limit bites.
  • Environment variable size: 4 KB.

The concurrency limit is up to 1000 concurrent executions. You can also set a reserved concurrency at the function level, which acts as a limit for that function.

Any invocation beyond the concurrency limit triggers a throttle, and the throttle behavior depends on how the function was invoked:

  • Synchronous invocation returns a ThrottleError – 429.
  • Asynchronous invocation is retried automatically, and then goes to a DLQ.

If you need a higher limit, you open a support ticket.

The concurrency problem when you do not reserve

Section titled “The concurrency problem when you do not reserve”

If you do not reserve — that is, limit — concurrency per function, functions steal capacity from each other. The deck’s illustration: one function fronted by an Application Load Balancer is hit by many users and consumes all 1000 concurrent executions; the functions behind API Gateway and behind the SDK / CLI, serving few users, are throttled even though their own traffic is tiny.

When events arrive asynchronously — for example new file events from an S3 bucket — and the function does not have enough concurrency available to process them all, the additional requests are throttled.

When the failure is a throttling error (429) or a system error (500-series), the event is not dropped: Lambda puts it back on the queue and keeps trying the function for as long as 6 hours. The gap between attempts grows exponentially, starting at 1 second after the first try and topping out at 5 minutes.

5. Cold starts, Provisioned Concurrency and SnapStart

Section titled “5. Cold starts, Provisioned Concurrency and SnapStart”

A cold start happens when a new instance of the function is created: the code is loaded and the code outside the handler runs (the init phase). If that init is large — lots of code, dependencies, SDKs — it takes time, and the first request served by a new instance has higher latency than the ones after it.

Provisioned Concurrency fixes this by allocating concurrency before the function is invoked, in advance. The cold start then never happens and all invocations have low latency. Application Auto Scaling can manage that concurrency, either on a schedule or against a target utilization.

The deck also notes that cold starts in a VPC were dramatically reduced in October and November 2019 — the historical penalty for VPC-attached functions is no longer what it was.

Lambda SnapStart improves function performance up to 10x at no extra cost, for Java, Python and .NET.

With it on, invocations start from a pre-initialized state rather than initializing the function from scratch. The work happens at publish time: for each new version, Lambda initializes the function once, snapshots the memory and disk state it reaches, then keeps that snapshot cached so it can be restored with low latency.

The difference shows in the invocation lifecycle. With SnapStart disabled, an invocation goes through Init, Invoke, Shutdown. With SnapStart enabled, the function is already pre-initialized, so the invocation is just Invoke, Shutdown.

Many modern applications execute some of their logic at the edge. An edge function is code you write and attach to CloudFront distributions; it runs close to your users to minimize latency.

CloudFront provides two types: CloudFront Functions and Lambda@Edge. In both cases you do not manage any servers, the code is deployed globally, you pay only for what you use, and the model is fully serverless. The use case is customizing CDN content.

The deck names ten places where edge functions earn their keep: keeping a website secure and private, running dynamic web applications at the edge, search engine optimization, routing requests intelligently between origins and data centers, stopping bots before they get further, transforming images in real time, A/B testing, authenticating and authorizing users, prioritizing some users over others, and tracking users for analytics.

CloudFront Functions are lightweight functions written in JavaScript, designed for high-scale, latency-sensitive CDN customizations. They offer sub-millisecond startup times and handle millions of requests per second.

They can only change viewer requests and responses:

  • Viewer Request — runs the moment a viewer’s request lands at CloudFront.
  • Viewer Response — runs just before the response leaves CloudFront for the viewer.

They are a native feature of CloudFront, so you manage the code entirely within CloudFront.

Lambda@Edge functions are written in Node.js or Python and scale to thousands of requests per second. They can change all four CloudFront hook points:

  • Viewer Request — on arrival of a viewer’s request at CloudFront.
  • Origin Request — on the way out, just before CloudFront hands the request to the origin.
  • Origin Response — once the origin’s response has come back to CloudFront.
  • Viewer Response — just before CloudFront sends the response on to the viewer.

You author the functions in one AWS region, us-east-1, and CloudFront replicates them to its locations.

CloudFront Functions Lambda@Edge
Runtime support JavaScript Node.js, Python
Number of requests Millions per second Thousands per second
CloudFront triggers Viewer Request/Response Viewer Request/Response, Origin Request/Response
Max execution time < 1 ms 5 – 10 seconds
Max memory 2 MB 128 MB up to 10 GB
Total package size 10 KB 1 MB – 50 MB
Network access, file system access No Yes
Access to the request body No Yes
Pricing Free tier available, 1/6th the price of Lambda@Edge No free tier, charged per request and duration

Their use cases split accordingly. CloudFront Functions handle cache key normalization (transforming headers, cookies, query strings and the URL into an optimal cache key), header manipulation, URL rewrites or redirects, and request authentication and authorization such as creating and validating user-generated tokens like JWT.

Lambda@Edge is for longer execution times (several milliseconds), adjustable CPU or memory, code that depends on third-party libraries such as the AWS SDK to reach other AWS services, network access to external services, and file system access or access to the body of HTTP requests.

By default your Lambda function is launched outside your own VPC, in an AWS-owned VPC. It can reach the public internet, but it cannot access resources in your VPC — a private RDS instance, ElastiCache, an internal ELB.

To give a function access to your VPC you define the VPC ID, the subnets and the security groups. Lambda then creates an ENI (Elastic Network Interface) in those subnets, and traffic flows from the Lambda security group to, say, the RDS security group as if the function were an instance in the subnet.

If Lambda functions access your database directly, they may open too many connections under high load — each concurrent execution is its own client.

RDS Proxy solves this:

  • It improves scalability by pooling and sharing DB connections.
  • It improves availability by reducing failover time by 66% and preserving connections.
  • It improves security by enforcing IAM authentication and storing credentials in Secrets Manager.

One requirement is non-negotiable: because RDS Proxy is never reachable publicly, the Lambda function has to be deployed inside your VPC.

The relationship also runs the other way: you can invoke Lambda functions from within your DB instance, which lets you process data events from inside a database. This is supported for RDS for PostgreSQL and Aurora MySQL.

Two conditions apply:

  • The DB instance must be allowed outbound traffic to the Lambda function — via a public path, a NAT gateway, or VPC endpoints.
  • The DB instance must have the required permissions to invoke the Lambda function, meaning both a Lambda resource-based policy and an IAM policy.

The deck’s example: a user registers, the INSERT on the RDS DB instance invokes a Lambda function, and the function uses Amazon SES to send the welcome email.

RDS Event Notifications tell you about the DB instance itself — created, stopped, started and so on. They give you no information about the data.

You subscribe to event categories covering the DB instance, DB snapshot, DB parameter group, DB security group, RDS Proxy and custom engine version. Events are near real time, up to 5 minutes. You can send notifications to SNS, or subscribe to the events using EventBridge, which then routes them to Lambda functions, SQS queues and other targets.

Amazon DynamoDB is fully managed and highly available with replication across multiple Availability Zones. It is a NoSQL database — not relational — with transaction support.

Its characteristics:

  • It scales to massive workloads and is a distributed database: millions of requests per second, trillions of rows, hundreds of TB of storage.
  • Performance is fast and consistent, at single-digit millisecond latency.
  • It is integrated with IAM for security, authorization and administration.
  • It is low cost with auto-scaling capabilities.
  • There is no maintenance or patching, and it is always available.
  • It offers a Standard and an Infrequent Access (IA) table class.

DynamoDB is made of tables. Each table has a Primary Key, which must be decided at creation time, and each table can hold an infinite number of items (rows). Each item has attributes, which can be added over time and can be null. The maximum size of an item is 400 KB.

The supported data types:

  • Scalar types — String, Number, Binary, Boolean, Null.
  • Document types — List, Map.
  • Set types — String Set, Number Set, Binary Set.

Because attributes are per-item rather than per-table, you can rapidly evolve schemas.

The deck’s example table shows the shape of a primary key made of two parts: User_ID is the Partition Key, Game_ID is the Sort Key, and together they form the Primary Key; Score and Result are ordinary attributes, and one row has a Score but the shape allows attributes to be absent.

Capacity mode controls how you manage a table’s read/write throughput.

Provisioned mode (the default):

  • You specify the number of reads and writes per second.
  • You need to plan capacity beforehand.
  • You pay for provisioned Read Capacity Units (RCU) and Write Capacity Units (WCU).
  • You can add auto-scaling for RCU and WCU.

On-demand mode:

  • Reads and writes scale up and down automatically with your workload.
  • No capacity planning is needed.
  • You pay for what you use, and it is more expensive.
  • It is great for unpredictable workloads with steep sudden spikes.

DAX is a fully managed, highly available, seamless in-memory cache for DynamoDB.

  • It solves read congestion by caching.
  • It delivers microsecond latency for cached data.
  • It does not require application logic modification, because it is compatible with existing DynamoDB APIs.
  • The cache TTL is 5 minutes by default.

The application talks to a DAX cluster of nodes, which sits in front of the DynamoDB tables.

A DynamoDB stream is an ordered stream of item-level modifications — create, update, delete — in a table. The use cases:

  • React to changes in real time, such as sending a welcome email to new users.
  • Real-time usage analytics.
  • Insert into derivative tables.
  • Implement cross-region replication.
  • Invoke AWS Lambda on changes to your DynamoDB table.

There are two stream options:

DynamoDB Streams Kinesis Data Streams (newer)
24 hours retention 1 year retention
Limited number of consumers High number of consumers
Processed using AWS Lambda triggers or the DynamoDB Stream Kinesis adapter Processed using AWS Lambda, Kinesis Data Analytics, Kinesis Data Firehose, AWS Glue Streaming ETL and others

Downstream, the processing layer branches to whatever you need: Lambda can send to Amazon SNS for messaging and notifications or write back to a DynamoDB table after filtering and transforming, and Kinesis Data Firehose can land the data in Amazon Redshift for analytics, Amazon S3 for archiving, or Amazon OpenSearch for indexing.

Global Tables make a DynamoDB table accessible with low latency in multiple regions using active-active replication: applications can read and write in any region, and the replication is two-way.

The prerequisite: DynamoDB Streams must be enabled.

TTL automatically deletes items after an expiry timestamp stored as an attribute on the item. An expiration process scans and expires items whose TTL has passed, and a deletion process then scans and deletes them.

Use cases: reducing stored data by keeping only current items, adhering to regulatory obligations, and web session handling.

Continuous backups using point-in-time recovery (PITR):

  • Optionally enabled for the last 35 days.
  • Recovery to any point in time within the backup window.
  • The recovery process creates a new table.

On-demand backups:

  • Full backups for long-term retention, kept until explicitly deleted.
  • They do not affect performance or latency.
  • They can be configured and managed in AWS Backup, which enables cross-region copy.
  • The recovery process creates a new table.

Export to S3PITR must be enabled:

  • Works for any point in time in the last 35 days.
  • Does not affect the read capacity of your table.
  • Lets you perform data analysis on top of DynamoDB, for example querying the export with Athena.
  • Lets you retain snapshots for auditing.
  • Lets you do ETL on the S3 data before importing it back into DynamoDB.
  • Exports in DynamoDB JSON or ION format.

Import from S3:

  • Imports CSV, DynamoDB JSON or ION format.
  • Does not consume any write capacity.
  • Creates a new table.
  • Import errors are logged in CloudWatch Logs.

The serverless API pattern is three boxes: a client calls a REST API on API Gateway, which proxies requests to Lambda, which performs CRUD operations on DynamoDB.

With AWS Lambda plus API Gateway there is no infrastructure to manage. What API Gateway brings:

  • Support for the WebSocket protocol.
  • API versioning (v1, v2 and so on).
  • Handling of different environments (dev, test, prod).
  • Security — authentication and authorization.
  • API keys and request throttling.
  • Swagger / OpenAPI import to define APIs quickly.
  • Transformation and validation of requests and responses.
  • SDK and API specification generation.
  • Caching of API responses.

Lambda Function — invoke a Lambda function. This is the easy way to expose a REST API backed by AWS Lambda.

HTTP — expose HTTP endpoints in the backend, for example an internal on-premises HTTP API or an Application Load Balancer. You do this to add rate limiting, caching, user authentication, API keys and similar in front of an existing backend.

AWS Service — expose any AWS API through API Gateway, for example starting an AWS Step Functions workflow or posting a message to SQS. The reasons are the same: authentication, public deployment, rate control. The deck’s example chains API Gateway to Kinesis Data Streams, then Kinesis Data Firehose, which stores .json files in Amazon S3.

  • Edge-Optimized (the default) — for global clients. Requests are routed through CloudFront edge locations, which improves latency, but the API Gateway itself still lives in only one region.
  • Regional — for clients within the same region. You could manually combine it with CloudFront, which gives you more control over caching strategies and the distribution.
  • Privatecan only be accessed from your VPC using an interface VPC endpoint (ENI), with a resource policy defining access.

User authentication comes in three flavors:

  • IAM roles — useful for internal applications.
  • Cognito — identity for external users, for example mobile users.
  • Custom Authorizer — your own logic.

Custom domain name HTTPS security works through integration with AWS Certificate Manager (ACM), and the certificate’s region depends on the endpoint type:

  • With an Edge-Optimized endpoint, the certificate must be in us-east-1.
  • With a Regional endpoint, the certificate must be in the API Gateway’s own region.

Either way, you must set up a CNAME or A-alias record in Route 53.

AWS Step Functions lets you build a serverless visual workflow to orchestrate your Lambda functions.

Its features cover sequence, parallel execution, conditions, timeouts and error handling. It can integrate with EC2, ECS, on-premises servers, API Gateway, SQS queues and more, and it offers the possibility of implementing a human approval step.

Use cases: order fulfillment, data processing, web applications — any workflow.

Amazon Cognito gives users an identity to interact with your web or mobile application. It has two distinct halves.

Cognito User Pools:

  • Sign-in functionality for your app’s users.
  • Integrates with API Gateway and the Application Load Balancer.

Cognito Identity Pools (Federated Identity):

  • Provide AWS credentials to users so they can access AWS resources directly.
  • Integrate with Cognito User Pools as an identity provider.

A user pool is effectively a serverless database of users for your web and mobile apps. It gives you:

  • Simple login with a username (or email) and password combination.
  • Password reset.
  • Email and phone number verification.
  • Multi-factor authentication (MFA).
  • Federated identities — users from Facebook, Google, SAML and so on.

The two integrations work like this. With API Gateway, the client authenticates against the user pool, retrieves a token, calls the REST API passing that token, and API Gateway evaluates the Cognito token before reaching the backend. With the Application Load Balancer, listeners and rules authenticate against the user pool before forwarding to the target group.

Cognito Identity Pools (Federated Identities)

Section titled “Cognito Identity Pools (Federated Identities)”

Identity pools get identities for users so they obtain temporary AWS credentials. The user source can be Cognito User Pools, third-party logins and others. Users can then access AWS services directly or through API Gateway.

The permissions are controlled from Cognito:

  • The IAM policies applied to the credentials are defined in Cognito.
  • They can be customized based on the user_id for fine-grained control.
  • There are default IAM roles for authenticated and guest users.

The flow: a web or mobile application logs in with a social identity provider or a Cognito User Pool and gets a token; it exchanges that token with the Cognito Identity Pool for temporary AWS credentials, which are validated; it then accesses a private S3 bucket or a DynamoDB table directly.

Because the policy can reference the user_id, this is also the mechanism for row-level security in DynamoDB — each user’s credentials only permit the rows belonging to that user.

Item What to remember for the exam
Serverless You do not manage, provision or see servers — but they exist; covers Lambda, DynamoDB, Cognito, API Gateway, S3, SNS/SQS, Kinesis Data Firehose, Aurora Serverless, Step Functions, Fargate
Lambda vs EC2 Lambda is limited by time, runs on demand and scales automatically; EC2 is limited by RAM/CPU, runs continuously and scales by intervention
Lambda resources Up to 10 GB RAM; increasing RAM also improves CPU and network
Lambda languages Node.js, Python, Java, C#/PowerShell, Ruby, Custom Runtime API; container images must implement the Lambda Runtime API, otherwise use ECS/Fargate
Lambda pricing First 1,000,000 requests and 400,000 GB-seconds free; then $0.20 per million requests and $1.00 per 600,000 GB-seconds, billed in 1 ms increments
Lambda limits Memory 128 MB – 10 GB, timeout 900 s (15 min), env vars 4 KB, /tmp 512 MB – 10 GB, concurrency 1000 (increasable), zip 50 MB, uncompressed 250 MB
Throttling Synchronous returns 429 ThrottleError; asynchronous retries automatically then goes to the DLQ; async events retry up to 6 hours, backing off from 1 second to 5 minutes
Reserved concurrency Set per function so one busy function cannot consume the whole account’s 1000 executions
Cold start Init runs on a new instance; Provisioned Concurrency allocates capacity in advance so the first request is fast, managed by Application Auto Scaling
SnapStart Up to 10x faster at no extra cost, for Java, Python and .NET; snapshots the initialized memory and disk state at publish time
CloudFront Functions JavaScript, < 1 ms, 2 MB memory, 10 KB package, viewer request/response only, no network or body access, 1/6th the price of Lambda@Edge
Lambda@Edge Node.js/Python, 5–10 s, 128 MB – 10 GB, 1–50 MB package, all four triggers, network, file system and request body access; authored in us-east-1
Lambda networking Runs outside your VPC by default; attaching it needs VPC ID, subnets, security groups and creates an ENI
RDS Proxy Pools connections, cuts failover time by 66%, enforces IAM auth with Secrets Manager; the Lambda function must be in your VPC
Lambda from the database Supported for RDS for PostgreSQL and Aurora MySQL; needs outbound traffic plus a Lambda resource-based policy and an IAM policy
RDS Event Notifications About the instance, never the data; near real time up to 5 minutes; delivered to SNS or EventBridge
DynamoDB NoSQL, multi-AZ, transactions, single-digit ms, item max 400 KB, primary key fixed at creation, Standard and Infrequent Access table classes
Capacity modes Provisioned (RCU/WCU, plan ahead, optional auto scaling) versus On-demand (no planning, more expensive, best for unpredictable spikes)
DAX In-memory cache for DynamoDB, microsecond latency, 5-minute TTL, no code changes; caches objects and query/scan results, whereas ElastiCache stores aggregation results
Streams DynamoDB Streams: 24 h, few consumers, Lambda triggers or the KCL adapter. Kinesis Data Streams: 1 year, many consumers, Lambda / Kinesis Data Analytics / Firehose / Glue
Global Tables Multi-region active-active, read and write anywhere; DynamoDB Streams must be enabled first
TTL Auto-deletes items past an expiry timestamp; used for session handling, data minimization and compliance
DynamoDB backups PITR for the last 35 days, or on-demand backups kept until deleted and manageable in AWS Backup (cross-region copy); both recover into a new table
DynamoDB and S3 Export needs PITR, does not touch read capacity, writes DynamoDB JSON or ION; import reads CSV, DynamoDB JSON or ION, consumes no write capacity, creates a new table, logs errors to CloudWatch Logs
API Gateway WebSocket support, versioning, environments, security, API keys and throttling, OpenAPI import, request/response transformation, SDK generation, response caching
API Gateway integrations Lambda, HTTP backends, and any AWS service — all so you can add auth, rate limiting and caching in front
Endpoint types Edge-Optimized (default, via CloudFront, API still in one region), Regional, Private (interface VPC endpoint plus resource policy)
API Gateway security IAM roles, Cognito, or a Custom Authorizer; ACM certificate in us-east-1 for edge-optimized and in the API’s region for regional, plus a Route 53 CNAME or A-alias
Step Functions Visual serverless workflow with sequence, parallel, conditions, timeouts, error handling and human approval
Cognito User Pools give sign-in and integrate with API Gateway and the ALB; Identity Pools exchange a token for temporary AWS credentials, with IAM policies defined in Cognito and customizable by user_id for row-level security