Skip to content

Repository files navigation

Lambda API

Serverless REST API built with AWS Lambda, API Gateway, DynamoDB, S3 and SQS, using Node.js + TypeScript and AWS SAM.

The entire application is developed and tested locally using Docker, SAM Local, DynamoDB Local, MinIO and ElasticMQ.

No AWS deployment is required.

Architecture

The project follows a simplified Clean Architecture approach:

API Gateway → Lambda Handler → Service → Repository → DynamoDB

CSV import pipeline:

CSV → MinIO (S3) → S3 Event Bridge → Lambda → ElasticMQ (SQS) → SQS Consumer → Lambda → DynamoDB

The current S3 flow uses a small local bridge because MinIO cannot directly invoke SAM Local Lambda endpoints.

The local SQS flow uses a small consumer because ElasticMQ cannot directly trigger SAM Local Lambda endpoints.


API Endpoints

Method Endpoint Description Status
POST /loyalty-cards Create a loyalty card
GET /loyalty-cards/{id} Get a loyalty card by ID
GET /loyalty-cards Get all loyalty cards

Progress

Create Loyalty Card

  • POST /loyalty-cards
  • LoyaltyCard model
  • LoyaltyCardService
  • Input validation
  • UUID generation
  • Initial points
  • Creation timestamp
  • DynamoDB persistence

DynamoDB & Repository

  • DynamoDB Local
  • Loyalty cards table
  • LoyaltyCardRepository
  • Create / Get / GetAll operations
  • Service → Repository → DynamoDB
  • Environment configuration
  • Lambda permissions
  • DynamoDB item mapping

Architecture & Error Handling

  • Separate handlers, services and repositories
  • Application/domain errors
  • HTTP error mapping
  • Centralized dependency creation
  • Centralized HTTP error handling if needed

Testing

  • Jest
  • Handler tests
  • Service unit tests
  • FakeLoyaltyCardRepository
  • Repository integration tests
  • Additional validation/error tests
  • Integration tests

CSV Import

  • MinIO configured as local S3
  • CSV import Lambda
  • CSV parsing
  • S3 ObjectCreated events
  • S3 Event Bridge
  • MinIO → Bridge → SAM Local
  • SQS
  • SQS-triggered Lambda
  • Persist imported cards through LoyaltyCardService
  • Retries and failed messages
  • Dead Letter Queue
  • End-to-end pipeline test

Local Infrastructure

  • API Gateway / SAM Local
  • DynamoDB Local
  • MinIO
  • Docker network
  • Persistent DynamoDB storage
  • Persistent MinIO storage
  • Automatic DynamoDB table creation
  • Automatic S3 bucket creation
  • SAM Lambda network configuration
  • Local S3 event bridge
  • SQS
  • SQS → Lambda consumer
  • DLQ
  • Complete infrastructure in template.yaml
  • One-command local setup

Project Structure

lambda-api/
├── src/
│   ├── handlers/          # Lambda handlers
│   ├── services/          # Business logic
│   ├── repositories/      # Data access
│   ├── models/            # Domain models
│   ├── errors/            # Application/domain errors
│   ├── infrastructure/    # AWS clients & dependencies
│   ├── local/             # Local development utilities
│   └── tests/             # Unit tests & test doubles
│
├── docker/
│   ├── dynamodb/          # DynamoDB initialization
│   ├── s3/                # S3/MinIO initialization
│   └── sqs/               # Local SQS configuration
│
├── events/                # Local test events & CSV files
├── template.yaml          # AWS SAM infrastructure
├── docker-compose.yml     # Local AWS infrastructure
├── jest.config.ts         # Jest configuration
└── package.json

Local Development

Prerequisites

  • Docker
  • Docker Compose
  • Node.js
  • npm
  • AWS CLI
  • AWS SAM CLI

No AWS account is required.

1. Install dependencies

npm install

2. Start local infrastructure

docker compose up -d

This starts:

  • DynamoDB Local
  • MinIO
  • ElasticMQ (local SQS)
  • Database, S3 and SQS initialization containers

Services are connected through the Docker network:

lambda-api

DynamoDB:

http://localhost:8000

MinIO S3 API:

http://localhost:9000

MinIO Console:

http://localhost:9001

ElasticMQ:

http://localhost:9324

Local AWS credentials:

Access Key: dummy
Secret Key: dummy123
Region: us-east-1

The loyalty-cards bucket, DynamoDB table and SQS queue are created automatically.

3. Build the SAM application

sam build

4. Start the REST API

sam local start-api --docker-network lambda-api

API:

http://localhost:3000

Example:

curl -X POST http://localhost:3000/loyalty-cards \
  -H "Content-Type: application/json" \
  -d '{"customerName":"Axel"}'
curl http://localhost:3000/loyalty-cards/{id}
curl http://localhost:3000/loyalty-cards

5. Start SAM Lambda endpoint

The local S3 bridge and SQS consumer invoke Lambda functions through SAM Local:

sam local start-lambda --docker-network lambda-api

SAM Lambda endpoint:

http://localhost:3001

This exposes the Lambda functions defined in template.yaml, including:

ImportLoyaltyCardsFunction
ProcessLoyaltyCardFunction

6. Start the S3 Event Bridge

npm run local:s3-bridge

The bridge listens on:

http://localhost:4000

It receives MinIO S3 events and invokes the corresponding Lambda through SAM Local.

The bridge is only required for the local environment. In AWS, S3 can invoke Lambda directly.

7. Start the local SQS consumer

npm run local:sqs-consumer

The consumer polls the local ElasticMQ queue and invokes ProcessLoyaltyCardFunction through SAM Local.

Queue:

http://localhost:9324/000000000000/loyalty-cards

The local consumer provides the SQS → Lambda integration used during local development.

In AWS, this integration would normally be handled by an SQS event source mapping instead of the local consumer.

8. Test CSV import

Upload a CSV to MinIO:

AWS_ACCESS_KEY_ID=dummy \
AWS_SECRET_ACCESS_KEY=dummy123 \
aws s3 cp events/cards.csv s3://loyalty-cards/cards.csv \
  --endpoint-url http://localhost:9000 \
  --region us-east-1

This triggers the local S3 event flow and invokes ImportLoyaltyCardsFunction.

The Lambda reads the CSV from MinIO, parses its contents and sends each loyalty card to SQS.

Example:

Parsed CSV:
[
  { customerName: 'Axel' },
  { customerName: 'Juan' },
  { customerName: 'Maria' }
]

The SQS consumer then processes each message through ProcessLoyaltyCardFunction, which reuses LoyaltyCardService to persist the cards in DynamoDB.

9. Run tests

npm test

Jest discovers tests under:

tests/**/*.test.ts

Unit tests use FakeLoyaltyCardRepository to test service logic without requiring DynamoDB.


Local Architecture

lambda-api-flow

Project Goal

The goal is to reproduce a serverless AWS architecture entirely locally and understand how the individual AWS components interact.

Local equivalents:

  • DynamoDB Local → DynamoDB
  • MinIO → S3
  • ElasticMQ → SQS
  • SAM Local → Lambda / API Gateway
  • Docker Compose → Local infrastructure
  • S3 Event Bridge → Local S3 → Lambda integration
  • SQS Consumer → Local SQS → Lambda integration

About

Fully local serverless AWS architecture using Lambda, API Gateway, DynamoDB, S3, SQS, Docker and AWS SAM.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages