A production-grade newsletter subscription service built with C# / ASP.NET Core 8. This project demonstrates enterprise infrastructure patterns and best practices β the business idea is a vehicle to showcase that given any idea, the surrounding infrastructure is just a few tweaks.
This is a portfolio project designed to demonstrate:
- Clean layered architecture that scales
- Production-ready AWS integration (SNS, SQS, DynamoDB)
- Infrastructure patterns transferable to any microservice
- Real-world concerns: connection pooling, idempotency, observability
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β NewsletterX.Host β
β (Composition Root) β
β Program.cs | DI | Configuration | Background Services β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β
βΌ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β NewsletterX.Api β
β (HTTP Layer) β
β Controllers | Middleware | Filters β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β
βΌ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β NewsletterX.Providers β
β (Business Logic) β
β IAuthProvider | ISubscriptionProvider | ISnsPublisher β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β
βΌ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β NewsletterX.Repositories β
β (Data Access) β
β IUserRepository | ISubscriptionRepository (PostgreSQL) β
β IEmailLogRepository (DynamoDB) β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β
βββββββββββββββββ΄ββββββββββββββββ
βΌ βΌ
βββββββββββββββββββββββββββββ βββββββββββββββββββββββββββββ
β NewsletterX.EntityModels β β NewsletterX.Types β
β EF Core + DynamoDB β β Enums | Constants β
βββββββββββββββββββββββββββββ βββββββββββββββββββββββββββββ
HTTP Request β Controller β Provider β Repository β Database/AWS
| Feature | Status | Description |
|---|---|---|
| JWT Authentication | π | Register, login, protected routes |
| User Management | π | CRUD operations with soft delete |
| Subscriptions | π | Subscribe/unsubscribe to newsletters |
| SNS Fan-out | π | One publish β multiple SQS queues |
| SQS Consumers | π | Background workers with DLQ |
| DynamoDB Audit | π | Append-only dispatch log with TTL |
| Rate Limiting | π | Protect auth endpoints |
| Health Checks | β | DB + SQS connectivity checks |
| Structured Logging | β | Serilog with correlation IDs |
- Runtime: .NET 8 / ASP.NET Core
- Primary DB: PostgreSQL via EF Core
- Audit Log: AWS DynamoDB
- Messaging: AWS SNS + SQS
- Auth: JWT Bearer tokens
- Logging: Serilog (structured)
- Local AWS: LocalStack
- Containers: Docker
- .NET 8 SDK
- Docker Desktop
- AWS CLI (optional, for verifying LocalStack)
cd deployment
docker-compose up -dThis starts:
- PostgreSQL on
localhost:5432 - LocalStack on
localhost:4566(SNS, SQS, DynamoDB)
cd src/NewsletterX.Host
dotnet runNavigate to: http://localhost:5000
# List SNS topics
aws --endpoint-url=http://localhost:4566 sns list-topics
# List SQS queues
aws --endpoint-url=http://localhost:4566 sqs list-queues
# List DynamoDB tables
aws --endpoint-url=http://localhost:4566 dynamodb list-tablesNewsletterX/
βββ src/
β βββ NewsletterX.Host/ # Entry point, DI, config
β β βββ Program.cs
β β βββ appsettings.json
β β βββ Configuration/ # Strongly-typed options
β β βββ BackgroundServices/ # SQS consumers, scheduled jobs
β β βββ HealthChecks/
β β
β βββ NewsletterX.Api/ # HTTP layer
β β βββ Controllers/
β β βββ Middleware/
β β βββ Filters/
β β
β βββ NewsletterX.Providers/ # Business logic
β β βββ Interfaces/
β β βββ Implementations/
β β βββ Options/ # Provider-specific config
β β βββ Messages/ # SQS/SNS message DTOs
β β
β βββ NewsletterX.Repositories/ # Data access
β β βββ Interfaces/
β β βββ Implementations/
β β βββ Extensions/
β β
β βββ NewsletterX.EntityModels/ # Persistence models
β β βββ PostgreSQL/ # EF Core entities
β β βββ DynamoDB/ # DynamoDB documents
β β
β βββ NewsletterX.ContractModels/ # API DTOs
β β βββ Requests/
β β βββ Responses/
β β βββ Validators/ # FluentValidation
β β
β βββ NewsletterX.Types/ # Shared primitives
β βββ Enums/
β βββ Constants/
β
βββ test/
β βββ NewsletterX.Tests/
β βββ Unit/
β βββ Integration/
β
βββ deployment/
β βββ docker-compose.yml
β βββ localstack-init/
β βββ init-aws.sh # Creates SNS/SQS/DynamoDB
β
βββ NewsletterX.sln
// PostgreSQL: Npgsql pools connections automatically
"Max Pool Size=50;Min Pool Size=5;Connection Idle Lifetime=300"
// DynamoDB: Client MUST be singleton (manages own HTTP pool)
services.AddSingleton<IAmazonDynamoDB, AmazonDynamoDBClient>();NewsletterDispatchProvider.DispatchAsync()
β
βΌ
SNS Topic (newsletter-dispatch)
β
ββββββββββββββββββ¬βββββββββββββββββ
βΌ βΌ βΌ
SQS Queue SQS Queue (future queues)
(email-send) (audit-log)
β β
βΌ βΌ
EmailSender AuditLogWorker
Worker β DynamoDB
Table: EmailDispatchLog
PK: NewsletterType (e.g., "weekly")
SK: DispatchTimestamp#DispatchId
TTL: Auto-delete after 90 days
[10:23:45 INF] abc123 | Processing subscription for user@example.com
[10:23:46 INF] abc123 | Published to SNS: newsletter-dispatch
[10:23:47 INF] abc123 | Logged dispatch to DynamoDB
Each file contains detailed comments explaining why decisions were made. Key documents:
src/NewsletterX.Host/appsettings.json- Configuration rationaledeployment/docker-compose.yml- Infrastructure decisionsdeployment/localstack-init/init-aws.sh- AWS resource design- Project
.csprojfiles - Dependency reasoning
# Run all tests
dotnet test
# Run with coverage
dotnet test --collect:"XPlat Code Coverage"MIT
Built to demonstrate production-grade infrastructure thinking. The newsletter is just the vehicle β the patterns are the product.