Based on the DEA-C01 exam guideReport an error
If EMR and Glue are "heavy engines for distributed large-scale processing," AWS Lambda is the opposite philosophy. No servers running, tiny code snippets execute the instant an event fires, then vanish. In data engineering, Lambda isn't "massive transformation"—it's "lightweight, instant, event-reactive transformation."
Today's core question is simple: when is Lambda appropriate, and when isn't it? Wrong Lambda choices hit time and memory walls, causing mid-task failure. Understanding that boundary precisely is critical for exams and real work.
Lambda is defined by three traits.
| Trait | Meaning |
|---|---|
| Event-driven | S3 PUT, Kinesis records, SQS messages etc. trigger the function |
| Stateless | Each invocation runs independently; no persistent in-memory state |
| Short-lived | Max 15 minutes execution then forced termination |
Lambda shines in data pipelines with S3 event-based transformation. A new file lands on S3, Lambda triggers instantly to transform, validate, and route it.
# Lambda triggered by S3 file arrival: JSON → clean → different bucket
import json
import boto3
s3 = boto3.client("s3")
def lambda_handler(event, context):
for record in event["Records"]:
bucket = record["s3"]["bucket"]["name"]
key = record["s3"]["object"]["key"]
obj = s3.get_object(Bucket=bucket, Key=key)
data = json.loads(obj["Body"].read())
# Lightweight transform: field cleaning and validation
cleaned = [r for r in data if r.get("amount", 0) > 0]
s3.put_object(
Bucket="curated-bucket",
Key=f"cleaned/{key}",
Body=json.dumps(cleaned),
)
return {"processed": len(event["Records"])}This pattern is powerful because idle cost is zero. No files, no execution, no charge. No need to keep Glue clusters running all night—process files only when they arrive, charged per 100ms.
💡 Related Theory: Lambda is the canonical FaaS (Function as a Service) implementation, the apex of compute abstraction. Compute progresses: physical servers → VMs (EC2) → containers (ECS) → functions (Lambda), with management units shrinking from "machines" to "code snippets." Higher abstraction cuts operational burden but adds runtime environment constraints and execution limits. Lambda's 15-minute cap is the direct result of this tradeoff.
When using Lambda for ETL, memorize these hard limits. They determine suitability.
| Item | Limit | Implication |
|---|---|---|
| Max execution time | 15 minutes | Long-running large-scale processing impossible |
| Memory | 128MB ~ 10,240MB(10GB) | Data too large for memory is unfit |
| /tmp temp disk | 512MB ~ 10GB | Large file buffering has limits |
| Sync payload | 6MB (request/response) | Large data needs S3 transit |
| Deployment package | 50MB (zipped) / 250MB (unzipped) | Large libraries need container images (10GB) |
Lambda's CPU is allocated proportional to memory. Raise memory and CPU rises too. Slow CPU-bound work gets faster via more memory, sometimes lowering total cost. This is Lambda's core cost-tuning insight.
⚠️ Gotcha: If you pick Lambda for "aggregate 100GB daily logs from S3," you'll be wrong. A single invocation with 15-min and 10GB memory limits can't handle massive data at once. Huge batch jobs need Glue or EMR. Lambda is strictly for "small file unit, short transform."
Draw the line clearly.
Fit
Unfit
# Kinesis Firehose transform Lambda: transform records, return status
import base64
import json
def lambda_handler(event, context):
output = []
for record in event["records"]:
payload = json.loads(base64.b64decode(record["data"]))
payload["processed_at"] = context.aws_request_id
transformed = base64.b64encode(
(json.dumps(payload) + "\n").encode("utf-8")
).decode("utf-8")
output.append({
"recordId": record["recordId"],
"result": "Ok",
"data": transformed,
})
return {"records": output}Firehose transform must return recordId and result (Ok/Dropped/ProcessingFailed) for each record. Firehose needs to track per-record success/failure.
🔍 Deeper Dive: Lambda's first invocation is slow due to cold start — spinning up a fresh execution environment (container). Later invocations reuse the warm environment and are faster. Data pipelines aren't usually sensitive to this latency, but if latency matters, Provisioned Concurrency can pre-warm environments. VPC-attached Lambda used to suffer long cold starts, but ENI improvements have greatly mitigated it.
Lambda's strength is automatic horizontal scaling. If 1,000 files land on S3 simultaneously, Lambda can invoke up to 1,000 instances in parallel (within account limits). For "many small file transforms," you get near-infinite parallelism without distributed clusters.
Protect downstreams via Reserved Concurrency or function concurrency limits. Without caps, Lambda invoking thousands of times to RDS kills the DB with connection storms.
# Cap concurrent function executions to 50 to protect downstream DB
aws lambda put-function-concurrency \
--function-name s3-transform \
--reserved-concurrent-executions 50🎯 Scenario: Thousands of IoT devices endlessly upload tiny JSON files to S3. Each under 1MB, transform is just cleaning. Optimal architecture: (1) S3 event → Lambda trigger transforms instantly, (2) save transformed Parquet to curation bucket, (3) Reserved Concurrency limits downstream load, (4) failures isolated to DLQ (SQS) for reprocessing. Zero idle cost, auto-scales with traffic. If files grow massive or complex aggregation needed, switch to Glue/EMR.
Lambda's retry behavior depends on invocation type. Async invocations (S3 events) retry up to 2 times by default, and if still failing, can send failed events to DLQ (Dead Letter Queue) or Lambda Destinations. Without this, failed events silently vanish—exactly what data pipelines must avoid.
Stream sources (Kinesis/DynamoDB Streams) behave differently. One record failing may block the shard, so options like BisectBatchOnFunctionError, MaximumRetryAttempts, and failure destination prevent "poison pill" records from halting the entire pipeline.
Lambda is a lightweight, event-driven, stateless transform tool with 15-minute cap. Ideal for "small and short" work like S3-arrival instant transform, Firehose record transform, and pipeline glue code. Zero idle cost and auto horizontal scaling are strengths. Large-scale, long-running, complex aggregation must go to Glue/EMR. Memorize limits (time, memory, payload), isolate failures with DLQ—these are reliability's core. Tomorrow we orchestrate multiple processing stages.
Click a choice to reveal the answer and explanation.
Question 1
You must decode a single 200 GB compressed log file that arrives in S3 every day and perform complex aggregations. Which of the following is the LEAST appropriate choice?
Question 2
Which fields must be included when returning each record from a Kinesis Data Firehose data transformation Lambda function?
Question 3
A Lambda function running a CPU-bound task is often slow, close to timing out. What is the first-line tuning that can also improve cost?
Question 4
A Lambda function triggered asynchronously by S3 events fails intermittently. What is the most appropriate way to ensure that failed events are not silently lost?
Question 5
Which of the following workloads is the best fit for Lambda-based transformation?