Python Serverless on AWS Lambda · Capstone Case Studies
Capstone: A Nightly Import of Five Million Rows
Design a reliable nightly import of a large partner CSV into DynamoDB with Python on AWS.
Scenario
Example company: a retailer receives a 5-million-row product CSV (about 3 GB) from a supplier every night at 01:00 in S3. Prices and stock must be updated in DynamoDB by 06:00. The current Python function downloads the file to /tmp, loads it with pandas and times out on most nights.
Requirements
- All valid rows are applied by 06:00; invalid rows are reported to the supplier with reasons.
- Re-running the import (after a failure or a corrected file) must not create duplicates or apply stale data over newer data.
- The team can see progress and which rows failed.
Constraints
- Python on Lambda, S3, SQS, Step Functions and DynamoDB are available; no long-running servers.
- The supplier sometimes sends the same file twice, and sometimes sends a corrected file at 03:00.
- DynamoDB writes must not throttle the live website reading the same table.
Deliverables
- The processing architecture: how the file is split and processed within Lambda's limits.
- Validation and error reporting for bad rows.
- Idempotency and ordering: duplicate files, re-runs and corrected files.
- Protecting the live table: write rate, capacity and backpressure.
- Observability: what you log and alarm on, and how you prove the import finished.
Hints
- Step Functions can iterate over the rows of a CSV in S3 directly.
- A file version or timestamp on each item lets you refuse stale writes.
- Concurrency limits apply to map runs and to queues.
Draft each deliverable below before revealing the model answer and rubric.
Further reading: Step Functions: Distributed Map · DynamoDB condition expressions
Deliverables
Describe the processing architecture.
Model answer
- S3
ObjectCreated(filtered to the supplier prefix) starts a Step Functions execution named after the object key and version (a duplicate start for the same file is rejected). - A Distributed Map reads the CSV directly from S3 and batches rows (for example 500 rows per child) into Python Lambda invocations with a concurrency limit (for example 40).
- Each child validates rows with Pydantic, writes valid rows with
batch_writer, and returns counts plus invalid rows. - Results are written to S3 by the map run; a final step aggregates counts and produces a report for the supplier.
Rubric
Look for splitting into small units processed in parallel (Distributed Map or SQS fan-out), not one long function; streaming rather than loading 3 GB into memory; and a final aggregation step.
Explain validation and error reporting.
Model answer
- A Pydantic model per row (types, ranges, required fields); invalid rows are collected with row number and reasons, not raised.
- The map run's failure tolerance is set so a few bad rows do not fail the whole import, while systemic failure (most rows invalid) stops it and alerts.
- The report (CSV of rejected rows with reasons) is stored in S3 and emailed or exposed to the supplier.
Rubric
Good answers separate row-level validation errors (expected, reported) from infrastructure failures (retried, alarmed) and set a tolerance threshold.
Handle idempotency, duplicates and corrected files.
Model answer
- Execution name = file key + version ID, so the same file cannot start two executions.
- Each item carries
source_file_ts; writes use a conditionattribute_not_exists(source_file_ts) OR source_file_ts <= :ts, so a re-run is harmless and a late, older file cannot overwrite newer data. - A corrected file at 03:00 has a newer timestamp, so it wins row by row; rows missing from the corrected file are handled explicitly (for example marked inactive in a final step) if the contract requires it.
Rubric
Look for conditional writes based on a source version or timestamp, and an explicit decision about rows absent from a newer file.
Protect the live table.
Model answer
- Limit total write throughput: map concurrency x batch size x writes per second per child must stay within the capacity reserved for the import (or on-demand limits), leaving headroom for the website.
- Handle throttling with SDK retries and backoff; if throttling persists, the map's concurrency is the lever to reduce.
- Run the import in the low-traffic window and monitor read latency of the site during it.
Rubric
Strong answers compute a target write rate and connect it to a concrete concurrency setting, rather than relying on retries alone.
Observability and proof of completion.
Model answer
- Structured logs per child batch (file, batch range, valid, invalid, duration) with Powertools Logger; metrics for rows applied, rows rejected, throttles.
- The execution's final state plus a reconciliation count (rows in file = applied + rejected) proves completion.
- Alarms: execution failed or not finished by 05:30, rejection rate above a threshold, DynamoDB throttling on the live table.
Rubric
Look for an explicit completeness check (counts reconcile) and a deadline alarm, not just error alarms.
Open in the app to mark lessons complete, take notes and track your progress.