A production-ready, enterprise-grade e-commerce backend API built with ASP.NET Core 9, featuring clean architecture, double-entry accounting, and comprehensive observability.
Features β’ Quick Start β’ Architecture β’ Documentation β’ API Reference
- Overview
- Features
- Architecture
- Tech Stack
- Quick Start
- Configuration
- Database Management
- API Reference
- Observability
- Testing
- Documentation
- Security
- Contributing
- License
The E-Commerce Backend API is a robust, scalable solution designed for modern e-commerce platforms. Built with clean architecture principles, it provides a solid foundation for managing products, orders, inventory, and customer data while maintaining full accounting traceability through double-entry bookkeeping.
β Clean Architecture - Layered design with clear separation of concerns (API, Application, Domain, Infrastructure) β Domain-Driven Design - Rich domain model with aggregates, value objects, policies, specifications, and domain events β Automated Accounting - Double-entry bookkeeping system compliant with Brazilian GAAP (NBC TG) β Enterprise Observability - Full OpenTelemetry integration for distributed tracing and metrics β Production Ready - Docker support, health checks, graceful shutdown, structured logging β Developer Experience - Interactive API documentation with Scalar UI, automated database seeding β Security First - JWT authentication, role-based authorization, password hashing with BCrypt
-
Authentication & Authorization
- JWT-based authentication with configurable expiration
- Role-based access control (Admin, Manager, Customer)
- Password hashing using BCrypt
- Token refresh and validation
-
Product Management
- Full CRUD operations with pagination
- Advanced search and filtering (category, price, rating)
- Featured products and sales management
- SKU-based inventory tracking
- Product specifications with value objects
-
Inventory & Accounting
- Real-time inventory tracking across multiple locations
- Automatic double-entry accounting for all inventory movements
- Transaction types: Purchase, Sale, Return, Adjustment, Loss, Transfer
- Full audit trail with traceability
- Chart of accounts seeded with 40+ predefined accounts
- Financial reports support (COGS, Trial Balance, Income Statement)
-
Business Rules Engine
- Pricing policies with discount validation
- Stock management with low-stock alerts
- Order validation and lifecycle management
- Coupon validation with usage limits
- Review moderation policies
- Fraud detection scoring
-
Domain-Driven Design
- Value Objects: Money, Discount, EmailAddress, SKU
- Policies: Pricing, Stock Management, Order Validation, Coupon Validation
- Specifications: Product and Order filtering criteria
- Domain Services: Discount Calculation, Order Lifecycle, Product Pricing, Fraud Detection
- Domain Events: Order Placed, Stock Alert, Product Price Changed, etc.
The solution follows Clean Architecture principles with four distinct layers:
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Presentation Layer β
β (src/API) β
β β’ Controllers (Auth, Products, Users, Accounting) β
β β’ Middlewares (Exception Handling) β
β β’ OpenAPI/Scalar Documentation β
β β’ OpenTelemetry Configuration β
ββββββββββββββββββββ¬βββββββββββββββββββββββββββββββββββββββββββ
β
ββββββββββββββββββββΌβββββββββββββββββββββββββββββββββββββββββββ
β Application Layer β
β (src/Application) β
β β’ Application Services (JWT, Password, Accounting) β
β β’ DTOs (Data Transfer Objects) β
β β’ Interfaces (Service Contracts) β
β β’ Mappings (AutoMapper profiles) β
ββββββββββββββββββββ¬βββββββββββββββββββββββββββββββββββββββββββ
β
ββββββββββββββββββββΌβββββββββββββββββββββββββββββββββββββββββββ
β Domain Layer β
β (src/Domain) β
β β’ Entities & Aggregates (User, Product, Order, etc.) β
β β’ Value Objects (Money, Discount, Email, SKU) β
β β’ Domain Services (Pricing, Order Lifecycle, Fraud) β
β β’ Policies (Pricing, Stock, Order, Coupon, Review) β
β β’ Specifications (Product, Order filtering) β
β β’ Domain Events (OrderPlaced, StockAlert, etc.) β
β β’ Domain Exceptions (Business rule violations) β
ββββββββββββββββββββ¬βββββββββββββββββββββββββββββββββββββββββββ
β
ββββββββββββββββββββΌβββββββββββββββββββββββββββββββββββββββββββ
β Infrastructure Layer β
β (src/Infrastructure) β
β β’ DbContext (PostgresqlContext - EF Core) β
β β’ Entity Configurations (Fluent API) β
β β’ Repositories (Generic + Specialized) β
β β’ Migrations (Code-First Database) β
β β’ Database Seeders (Admin User, Chart of Accounts) β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
- API β Application β Domain β Infrastructure
- Dependencies flow inward; Domain has no external dependencies
- Infrastructure implements interfaces defined in Domain/Application
- Repository Pattern - Data access abstraction
- Unit of Work - EF Core DbContext
- Specification Pattern - Reusable query criteria
- Domain Events - Decoupled business logic
- Value Objects - Immutable, self-validating domain concepts
- Aggregate Root - Consistency boundaries
- ASP.NET Core 9.0 - High-performance web framework
- C# 12 - Latest language features
- PostgreSQL 16 - Robust relational database
- Entity Framework Core 9.0 - ORM with code-first migrations
- Npgsql 9.0 - PostgreSQL provider for EF Core
- JWT Bearer Authentication - Stateless authentication
- BCrypt - Password hashing
- Role-Based Authorization - Fine-grained access control
- Microsoft.AspNetCore.OpenApi - OpenAPI 3.0 specification
- Scalar.AspNetCore 2.9 - Modern, interactive API documentation UI
- OpenTelemetry 1.13 - Distributed tracing and metrics
- OpenTelemetry.Instrumentation.AspNetCore - HTTP request tracing
- OpenTelemetry.Instrumentation.EntityFrameworkCore - Database query tracing
- OpenTelemetry.Instrumentation.Http - HTTP client tracing
- OpenTelemetry.Instrumentation.Runtime - .NET runtime metrics
- OpenTelemetry.Exporter.OpenTelemetryProtocol - OTLP/gRPC exporter
- Jaeger - Distributed tracing UI (Docker image)
- Docker - Application containerization
- Docker Compose - Multi-container orchestration
- Alpine Linux - Minimal base images for security and size
- .NET CLI - Command-line interface for .NET
- EF Core CLI - Database migrations and scaffolding
Ensure you have the following installed:
- .NET SDK 9.0+
- Docker Desktop (for Docker-based development)
- PostgreSQL 16+ (for local development without Docker)
- Git
You have two ways to build and run the application:
Uses your local PostgreSQL installation. Ideal for rapid development with hot reload.
Windows CMD:
cd scripts
build-local.cmdPowerShell:
cd scripts
.\build-local.ps1Requirements:
- PostgreSQL running locally on port 5432
- Database credentials configured in
appsettings.json
What it does:
- β Increments project version
- β Creates new EF Core migration
- β Builds project (Debug & Release)
- β Publishes artifacts
- β Exports SQL migration scripts
- β Applies migrations to local database
Runs everything in Docker containers with isolated PostgreSQL. Ideal for testing production-like environments.
Windows CMD:
cd scripts
build-docker.cmdPowerShell:
cd scripts
.\build-docker.ps1Requirements:
- Docker Desktop installed and running
- No local PostgreSQL needed
What it does:
- β Creates Docker network
- β Starts PostgreSQL container
- β Builds development image (port 5049)
- β Builds production image (port 8080)
- β Starts both containers with database connectivity
Containers created:
ecommerce-postgres- PostgreSQL 16 Alpineecommerce-backend-dev- Development modeecommerce-backend-prod- Production mode
Cleanup Docker containers:
cd scripts
.\cleanup-docker.ps1 # PowerShell
cleanup-docker.cmd # CMDgit clone https://github.com/mgnischor/ecommerce-backend.git
cd ecommerce-backendFor Local Development:
# Start local PostgreSQL (if not already running)
# Then run:
cd scripts
.\build-local.ps1For Docker Development:
cd scripts
.\build-docker.ps1Local Build:
- API:
https://localhost:5049 - API Docs:
https://localhost:5049/docs
Docker Build:
- Development API:
http://localhost:5049 - Production API:
http://localhost:8080 - PostgreSQL:
localhost:5432 - API Docs (Dev):
http://localhost:5049/docs - API Docs (Prod):
http://localhost:8080/docs
On first run, an admin user is automatically seeded:
- Email:
[email protected] - Password:
admin
β οΈ Important: Change these credentials immediately in production!
For a complete environment with Jaeger tracing:
docker-compose -f docker-compose.dev.yml up -dServices:
- API:
http://localhost:5049 - API Docs:
http://localhost:5049/docs - PostgreSQL:
localhost:5432 - Jaeger UI:
http://localhost:16686
docker-compose up -dServices:
- API:
http://localhost - PostgreSQL:
localhost:5432 - Jaeger UI:
http://localhost:16686
# Development
docker-compose -f docker-compose.dev.yml down
# Production
docker-compose down
# Remove volumes (database data)
docker-compose down -vFor detailed information about all build scripts, see scripts/README.md.
Configuration is managed through appsettings.json and appsettings.Development.json. Settings can be overridden via environment variables using the double-underscore syntax.
{
"ConnectionStrings": {
"DefaultConnection": "Host=localhost;Database=ecommerce;Username=ecommerce;Password=ecommerce;Port=5432"
}
}Environment Variable:
$env:ConnectionStrings__DefaultConnection = "Host=localhost;Database=ecommerce;Username=ecommerce;Password=ecommerce;Port=5432"{
"Jwt": {
"SecretKey": "your-secret-key-min-32-chars",
"Issuer": "ECommerceBackend",
"Audience": "ECommerceClient",
"ExpirationMinutes": "60"
}
}Environment Variables:
$env:Jwt__SecretKey = "your-strong-secret-key-here"
$env:Jwt__Issuer = "ECommerceBackend"
$env:Jwt__Audience = "ECommerceClient"
$env:Jwt__ExpirationMinutes = "60"{
"OpenTelemetry": {
"ServiceName": "ECommerce.Backend",
"ServiceVersion": "0.1.17",
"EnableConsoleExporter": false,
"OtlpEndpoint": ""
}
}Environment Variables:
$env:OpenTelemetry__ServiceName = "ECommerce.Backend"
$env:OpenTelemetry__ServiceVersion = "0.1.17"
$env:OpenTelemetry__EnableConsoleExporter = "true"
$env:OpenTelemetry__OtlpEndpoint = "http://localhost:4317"{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning",
"Microsoft.EntityFrameworkCore": "Warning"
}
}
}The project uses Entity Framework Core Code-First Migrations for database schema management.
dotnet ef database updatedotnet ef migrations add <MigrationName> --output-dir src/Infrastructure/Migrations --context PostgresqlContextdotnet ef migrations script --output migrations.sqldotnet ef migrations removeThe application automatically seeds the database on first run:
-
Admin User
- Email:
[email protected] - Password:
admin - Role: Admin
- Email:
-
Chart of Accounts (40+ accounts)
- Assets (Cash, Bank, Inventory, Receivables)
- Liabilities (Payables, Loans, Taxes)
- Equity (Capital, Retained Earnings)
- Revenue (Sales, Services, Other Income)
- Expenses (COGS, Operating, Financial)
Seeding logic: src/Infrastructure/Persistence/DatabaseSeeder.cs
PowerShell scripts are available in the scripts/ directory:
build-local.ps1- Complete build pipeline (version bump, migration, build, publish, SQL export)migration-script.ps1- Export migration SQL scriptsupdate-version.ps1- Bump project version
- Development:
https://localhost:5049/api/v1 - Docker (Dev):
http://localhost:5049/api/v1 - Docker (Prod):
http://localhost/api/v1
POST /api/v1/login
Content-Type: application/json
{
"email": "[email protected]",
"password": "admin"
}Response:
{
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"expiresIn": 3600,
"tokenType": "Bearer",
"userId": "...",
"email": "[email protected]",
"accessLevel": "Admin"
}| Method | Endpoint | Description | Auth |
|---|---|---|---|
| GET | /products |
List all products (paginated) | No |
| GET | /products/{id} |
Get product by ID | No |
| GET | /products/sku/{sku} |
Get product by SKU | No |
| GET | /products/category/{id} |
Get products by category | No |
| GET | /products/featured |
Get featured products | No |
| GET | /products/on-sale |
Get products on sale | No |
| GET | /products/search?searchTerm={term} |
Search products | No |
| POST | /products |
Create product | Admin/Manager |
| PUT | /products/{id} |
Update product | Admin/Manager |
| PATCH | /products/{id}/soft-delete |
Soft delete product | Admin/Manager |
| DELETE | /products/{id} |
Hard delete product | Admin |
| Method | Endpoint | Description | Auth |
|---|---|---|---|
| GET | /users |
List all users (paginated) | Yes |
| GET | /users/{id} |
Get user by ID | Yes |
| POST | /users |
Create user | Yes |
| PUT | /users/{id} |
Update user | Yes |
| DELETE | /users/{id} |
Delete user | Yes |
| Method | Endpoint | Description | Auth |
|---|---|---|---|
| POST | /inventory-transactions |
Record transaction | Yes |
| GET | /inventory-transactions/{id} |
Get transaction by ID | Yes |
| GET | /inventory-transactions/product/{id} |
Get product transactions | Yes |
| GET | /inventory-transactions/period?startDate={}&endDate={} |
Get transactions by period | Yes |
| Method | Endpoint | Description | Auth |
|---|---|---|---|
| GET | /accounting/chart-of-accounts |
List all accounts | Yes |
| GET | /accounting/chart-of-accounts/{id} |
Get account by ID | Yes |
| GET | /accounting/journal-entries |
List journal entries (paginated) | Yes |
| GET | /accounting/journal-entries/{id} |
Get journal entry by ID | Yes |
| GET | /accounting/journal-entries/product/{id} |
Get entries by product | Yes |
Protected endpoints require a JWT token in the Authorization header:
Authorization: Bearer <your-jwt-token>Access the Scalar UI at /docs for interactive API exploration:
- Try out endpoints directly from the browser
- View request/response schemas
- Download OpenAPI specification (JSON/YAML)
- Explore all available operations
The application is fully instrumented with OpenTelemetry for distributed tracing, metrics, and logging.
Automatic instrumentation is enabled for:
- ASP.NET Core - HTTP request/response tracking with status codes, durations, and exceptions
- Entity Framework Core - Database queries with SQL statements and execution times
- HTTP Client - Outgoing HTTP requests with URIs and response codes
- .NET Runtime - Garbage collection, thread pool, and exception metrics
When running with Docker Compose, Jaeger is available at:
URL: http://localhost:16686
Features:
- View end-to-end request traces
- Analyze service dependencies
- Identify performance bottlenecks
- Troubleshoot errors with full stack traces
- Monitor request latency percentiles (p50, p75, p95, p99)
Add custom spans to your code:
using ECommerce.API.Extensions;
public async Task<Order> ProcessOrderAsync(Guid orderId)
{
using var activity = ActivityHelper.StartActivity("ProcessOrder");
activity?.SetTag("order.id", orderId);
try
{
// Your business logic
var order = await _orderRepository.GetByIdAsync(orderId);
ActivityHelper.AddEvent("OrderRetrieved");
ActivityHelper.SetStatus(ActivityStatusCode.Ok);
return order;
}
catch (Exception ex)
{
ActivityHelper.RecordException(ex);
throw;
}
}Available metrics include:
-
HTTP Metrics
http.server.request.duration- Request duration histogramhttp.server.active_requests- Active requests gauge
-
Database Metrics
- Query execution times
- Connection pool statistics
-
Runtime Metrics
process.runtime.dotnet.gc.collections.count- GC collectionsprocess.runtime.dotnet.thread_pool.threads.count- Thread pool sizeprocess.runtime.dotnet.exceptions.count- Exception count
Enable in appsettings.Development.json:
{
"OpenTelemetry": {
"EnableConsoleExporter": true
}
}Traces and metrics will be printed to the console.
Configure the OTLP endpoint for your observability backend:
Jaeger:
{
"OpenTelemetry": {
"OtlpEndpoint": "http://jaeger:4317"
}
}Grafana Cloud / Tempo:
{
"OpenTelemetry": {
"OtlpEndpoint": "https://otlp-gateway-prod-us-central-0.grafana.net/otlp"
}
}Honeycomb:
{
"OpenTelemetry": {
"OtlpEndpoint": "https://api.honeycomb.io:443"
}
}All logs include contextual information:
_logger.LogInformation(
"Order created: OrderId={OrderId}, CustomerId={CustomerId}, Total={Total}",
order.Id,
order.CustomerId,
order.TotalAmount
);Log Levels:
Trace- Very detailed diagnostic informationDebug- Debugging informationInformation- General informational messagesWarning- Warnings that don't prevent executionError- Errors that stop the current operationCritical- Critical errors that require immediate attention
The project includes a comprehensive unit test suite located in the tests/ directory.
Tech Stack:
- NUnit - Testing framework
- FluentAssertions - Fluent assertion library
- Moq - Mocking library
- EF Core InMemory - For database testing
Structure:
tests/
βββ API/ # Controller and Middleware tests
βββ Application/ # Service and Validator tests
βββ Domain/ # Entity and Value Object tests
βββ Infrastructure/ # Repository tests
You can run the tests using the .NET CLI or the provided PowerShell scripts.
Using .NET CLI:
dotnet testUsing Scripts:
cd tests/scripts
.\run-tests.ps1With Coverage:
cd tests/scripts
.\run-tests-with-coverage.ps1Use the interactive Scalar UI at /docs to manually test endpoints.
Comprehensive documentation is available in the docs/ directory:
- BUSINESS_RULES.md - Domain policies, specifications, value objects, and business logic
- ACCOUNTING_SYSTEM.md - Double-entry accounting implementation following NBC TG
- ACCOUNTING_INTEGRATION_GUIDE.md - How to integrate accounting in your code
- OPENTELEMETRY_GUIDE.md - Complete OpenTelemetry setup and custom instrumentation
- RUNNING_WITH_JAEGER.md - Running and troubleshooting with Jaeger
- CHANGELOG.md - Version history and changes
- CONTRIBUTING.md - Contribution guidelines
- SECURITY_REVIEW.md - Security considerations and best practices
- JWT Bearer Tokens with configurable expiration
- BCrypt password hashing with salt
- Role-based authorization (Admin, Manager, Customer)
β Never commit secrets - Use environment variables or secure vaults β Strong JWT secret - Minimum 32 characters, randomly generated β HTTPS in production - Enable SSL/TLS certificates β Input validation - All DTOs use data annotations β SQL injection protection - EF Core parameterized queries β CORS configuration - Configure allowed origins in production β Rate limiting - Implement rate limiting middleware (planned) β Security headers - Add HSTS, CSP, X-Frame-Options (planned)
Before deploying to production:
- Change default admin credentials
- Use strong, randomly generated JWT secret key
- Enable HTTPS with valid SSL certificates
- Configure CORS for specific origins
- Set up database backups and disaster recovery
- Enable application insights and monitoring
- Review and implement security headers
- Configure rate limiting and throttling
- Set up Web Application Firewall (WAF)
- Perform security audit and penetration testing
See SECURITY_REVIEW.md for detailed security guidelines.
Contributions are welcome! Please follow these guidelines:
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
- Follow Clean Architecture principles
- Write meaningful commit messages
- Add XML documentation to public APIs
- Follow .NET coding conventions
- Ensure no breaking changes without discussion
- Update documentation for new features
Read CONTRIBUTING.md for detailed contribution guidelines.
This project is licensed under the GNU General Public License v3.0 (GPL-3.0-only).
See the LICENSE.md file for full license text.
- β You can use, modify, and distribute this software
- β You must disclose source code when distributing
- β You must use the same GPL-3.0 license for derivative works
- β You must state changes made to the code
- β No warranty or liability is provided
Miguel Nischor
- GitHub: @mgnischor
- Repository: ecommerce-backend
- ASP.NET Core Team - For the excellent framework
- EF Core Team - For the powerful ORM
- OpenTelemetry Community - For observability standards
- PostgreSQL Team - For the robust database
- Scalar Team - For the beautiful API documentation UI
β If you find this project useful, please consider giving it a star! β
Made with β€οΈ using ASP.NET Core 9