Customer Onboarding App
A serverless identity-verification (KYC) pipeline for a bank — no person in the loop on the happy path.
- AWS Step Functions
- AWS Lambda
- Amazon SQS
- Amazon Rekognition
- Amazon Textract
- Amazon DynamoDB
- Amazon SNS
- API Gateway
- AWS X-Ray
- AWS SAM
A new customer submits their application details, a selfie, and a photo of their driver's license. The backend matches the selfie to the license photo, checks the license details against what they typed in, validates the license number with a third-party service, and records every outcome in DynamoDB.
I built the first version as a single Lambda that did everything, then refactored it into seven single-purpose functions orchestrated by Step Functions. Each function has its own least-privilege IAM role, so a failure points at one step instead of the whole pipeline, and the workflow only continues when both identity checks pass.
Architecture
Results land in DynamoDB; any failed check fires a KMS-encrypted SNS alert.
How a submission flows
Unzip— Triggered by an S3 upload. Extracts the customer's zip (details CSV, selfie, license photo) and starts the state machine.WriteDynamo— Reads the details CSV and writes the customer record to DynamoDB.CompareFaces— Rekognition compares the selfie to the license photo at an 80% similarity threshold.CompareDetails— Textract AnalyzeID reads the license and checks 8 fields — name, date of birth, address, document number — against the application.SendToQueue— Runs only if both checks pass. Puts the license number on an SQS queue.SubmitLicense— Triggered by the queue. Calls the third-party validation API through API Gateway and records the result.
Design decisions
- Step Functions holds the order of steps, the parallel branch, and the “only continue if both checks pass” rule in one definition instead of spreading it across function code.
- SQS in front of the third-party call keeps a slow or failing provider from blocking identity verification; the dead-letter queue catches messages that keep failing so nothing is lost.
- X-Ray on every function — enabling it only on the state machine gave an empty map. Tracing everywhere produces one trace that follows a request across the whole pipeline.
- Everything as code — one SAM template defines the stack: HTTPS-only S3, DynamoDB auto scaling (2–20 units at 70%), the state machine, queues, API, and a separate inline-policy role per function.