A serverless weather API built with .NET 10, AWS Lambda, DynamoDB, and deployed using AWS CDK. This project demonstrates hexagonal architecture principles with clean separation of concerns.
This project follows Hexagonal Architecture (Ports and Adapters):
├── src/
│ ├── WeatherApi.Core/ # Domain & Use Cases (Business Logic)
│ │ ├── Domain/Entities/ # Domain models
│ │ ├── Ports/ # Interfaces (Repository, Service)
│ │ └── UseCases/ # Application business logic
│ ├── WeatherApi.Infrastructure/ # Adapters (External implementations)
│ │ ├── Adapters/
│ │ │ ├── Persistence/ # DynamoDB repository
│ │ │ └── External/ # OpenWeatherMap API client
│ │ └── DependencyInjection.cs
│ └── WeatherApi.Lambda/ # API Entry Point (AWS Lambda)
│ └── Program.cs # Minimal API endpoints
├── tests/
│ └── WeatherApi.Tests/ # Unit tests
└── infrastructure/ # AWS CDK Infrastructure as Code
├── lib/
│ └── weather-api-stack.ts # CDK stack definition
└── bin/
└── app.ts # CDK app entry point
- ✅ Hexagonal Architecture: Clean separation between domain, application, and infrastructure layers
- ✅ .NET 10 Minimal API: Modern, performant API endpoints
- ✅ AWS Lambda: Serverless compute with automatic scaling
- ✅ DynamoDB: NoSQL database for weather data storage
- ✅ Dependency Injection: Built-in DI container
- ✅ Swagger UI: Interactive API documentation at
/swagger - ✅ Unit Tests: XUnit with Moq and FluentAssertions
- ✅ Infrastructure as Code: AWS CDK for reproducible deployments
- ✅ OpenWeatherMap Integration: Real-time weather data
- .NET 10 SDK
- Node.js 18+ (for AWS CDK)
- AWS CLI configured with credentials
- AWS CDK installed:
npm install -g aws-cdk - OpenWeatherMap API Key (get free key at openweathermap.org)
cd serverless-weatherapidotnet restore
dotnet build
dotnet testcd src/WeatherApi.Lambda
dotnet publish -c Release -o bin/Release/net10.0/publish
cd ../..cd infrastructure
npm install
# Set your OpenWeatherMap API key
export OPENWEATHER_API_KEY="your_api_key_here"
# Deploy to AWS
cdk bootstrap # First time only
cdk deployThe CDK will output:
- ApiUrl: Your API endpoint
- SwaggerUrl: Swagger UI documentation
- TableName: DynamoDB table name
GET /api/weather/current/{city}Example:
curl https://your-api-url/api/weather/current/LondonGET /api/weather/forecast/{city}?days=5Example:
curl "https://your-api-url/api/weather/forecast/Paris?days=5"GET /api/weather/history?count=10DELETE /api/weather/{id}GET /healthGET /swagger| Variable | Description | Required |
|---|---|---|
OPENWEATHER_API_KEY |
OpenWeatherMap API key | Yes |
TABLE_NAME |
DynamoDB table name | Yes (auto-set by CDK) |
ASPNETCORE_ENVIRONMENT |
ASP.NET environment | No (defaults to Production) |
dotnet testFor local testing (requires AWS credentials configured):
cd src/WeatherApi.Lambda
export OPENWEATHER_API_KEY="your_key"
export TABLE_NAME="WeatherData"
dotnet runcd infrastructure
# Show what will be deployed
cdk diff
# Deploy stack
cdk deploy
# Destroy stack
cdk destroy
# Synthesize CloudFormation template
cdk synth- Entities:
WeatherData,WeatherForecast- Domain models - Ports: Interfaces defining contracts (
IWeatherRepository,IWeatherService) - Use Cases: Business logic (
GetCurrentWeatherUseCase,GetWeatherForecastUseCase)
- DynamoDbWeatherRepository: DynamoDB implementation of
IWeatherRepository - OpenWeatherMapService: External API client implementing
IWeatherService - DependencyInjection: Wires up all dependencies
- Program.cs: Minimal API endpoints with Swagger configuration
- Maps HTTP requests to use cases
- Handles serialization, validation, error responses
- .NET 10: Latest version with minimal API
- AWS Lambda: Serverless compute
- Amazon DynamoDB: Managed NoSQL database
- API Gateway HTTP API: API endpoint management
- AWS CDK: Infrastructure as Code (TypeScript)
- Swashbuckle: OpenAPI/Swagger documentation
- XUnit: Testing framework
- Moq: Mocking framework
- FluentAssertions: Assertion library
- Hexagonal Architecture (Ports & Adapters)
- Dependency Injection
- Repository Pattern
- Use Case Pattern
- Factory Pattern (HttpClient)
- Caching: Weather data is cached in DynamoDB for 30 minutes
- Lambda cold starts: ~1-2 seconds (optimized with AWS Lambda SnapStart compatible)
- DynamoDB: On-demand billing for cost optimization
- API Gateway: HTTP API for lower latency than REST API
With AWS Free Tier:
- Lambda: 1M requests/month free
- DynamoDB: 25GB storage + 200M requests/month free
- API Gateway: 1M requests/month free (12 months)
Estimated cost after free tier: ~$1-5/month for low-moderate traffic
- IAM roles with least-privilege permissions
- API key for OpenWeatherMap stored as environment variable
- CORS enabled for frontend integration
- DynamoDB encryption at rest (default)
- AWS CloudWatch Logs: Lambda execution logs
- AWS X-Ray: Distributed tracing (enabled)
- CloudWatch Metrics: Lambda invocations, duration, errors
- Follow hexagonal architecture principles
- Add tests for new use cases
- Update CDK stack for infrastructure changes
- Document API changes in Swagger annotations
MIT License
Evopoc Team
For issues or questions, please open an issue in the repository.