A production-ready event-driven wallet system with strong consistency guarantees, real-time analytics, and fraud detection.
- Deposits, Withdrawals & Transfers with ACID guarantees
- Idempotency via request IDs for all operations
- Immutable Event Log for complete audit trail
- Background Worker for analytics and fraud detection
- RabbitMQ for asynchronous event processing
- Dead Letter Queue (DLQ) for fault tolerance
- Pessimistic Locking for concurrency control
- Real-time Analytics and fraud detection
- Project Structure
- Technology Stack
- Quick Start
- API Documentation
- Background Worker
- Testing
- Monitoring & Logging
- Development
.
βββ services/
β βββ api/ # NestJS HTTP API service
β βββ worker/ # NestJS event worker service
βββ libs/
β βββ common/ # Shared enums, types, and event contracts
β βββ db-orm/ # TypeORM entities shared across services
βββ tools/
β βββ monkey-test.js # Load testing utility
βββ docker-compose.yml
βββ DESIGN.md # Detailed architecture documentation
βββ README.md
| Category | Technologies |
|---|---|
| Runtime | Node.js, TypeScript |
| Framework | NestJS |
| Database | PostgreSQL 16 |
| ORM | TypeORM |
| Message Broker | RabbitMQ |
| Testing | Jest |
| DevOps | Docker, Docker Compose |
| Package Manager | NPM Workspaces |
- Node.js 18+
- Docker & Docker Compose
- npm 9+
# Install dependencies
npm installCreate a .env at the repo root (see Environment Variables or copy .env.example) so the API and worker containers get DB/RabbitMQ settings:
# Start all services
docker-compose up --buildThis starts:
| Service | URL/Port | Credentials |
|---|---|---|
| API | http://localhost:3000 | - |
| Swagger UI | http://localhost:3000/api | - |
| PostgreSQL | localhost:5432 | wallet / wallet |
| RabbitMQ UI | http://localhost:15672 | guest / guest |
| RabbitMQ AMQP | localhost:5672 | guest / guest |
The API is fully documented using Swagger/OpenAPI. Once the services are running, visit:
http://localhost:3000/docs
This provides:
- Complete endpoint documentation
- Interactive API testing
- Request/response schemas
- Validation rules
To generate a static swagger.json file:
cd services/api
npm run generate:swagger| Endpoint | Method | Description |
|---|---|---|
/wallet/:id/deposit |
POST | Deposit funds into a wallet |
/wallet/:id/withdraw |
POST | Withdraw funds from a wallet |
/wallet/:id/transfer |
POST | Transfer funds between wallets |
/wallet/:id |
GET | Get wallet balance and details |
/wallet/:id/history |
GET | Get transaction history |
/wallet/:id/stats |
GET | Get wallet statistics |
π‘ Tip: All write operations support idempotency via the
requestIdfield.
The worker service processes events asynchronously and provides:
- Tracks total deposited/withdrawn amounts
- Monitors transfer activity (in/out)
- Records last activity timestamp
- Maintains per-wallet statistics
Rule 1: Rapid Withdrawals
- Flags wallets with β₯3 withdrawals within 60 seconds
Rule 2: Large Transactions
- Flags single withdrawals β₯ configurable threshold (default: 10,000)
wallet.events.worker (main queue)
β
[Processing]
β
Success β ACK
β
Failure β NACK β wallet.events.worker.dlq (DLQ)
Dead Letter Queue (DLQ):
- Failed messages are routed to
wallet.events.worker.dlq - Messages can be inspected and replayed manually
- Prevents poison messages from blocking the queue
API Service:
cd services/api
npm testCoverage:
- β Deposit/Withdraw/Transfer operations
- β Idempotency guarantees
- β Saga pattern & compensation
- β Event emission
Worker Service:
cd services/worker
npm testCoverage:
- β Analytics aggregation
- β Fraud detection rules
- β Worker idempotency
Validate the system under high concurrency:
# Default: 1000 requests, 100 concurrent
npm run monkeyValidates:
- Pessimistic row-level locking
- Saga correctness for transfers
- Idempotency under retry load
- No race conditions
- Worker throughput
Script: tools/monkey-test.js
Logs are written to:
logs/api.log # API service logs
logs/worker.log # Worker service logs
Features:
- JSON format for structured logging
- Automatic log rotation
- Configurable log levels
- Winston logger integration
All POST requests are recorded in the api_audit table:
| Field | Description |
|---|---|
method |
HTTP method |
url |
Request URL |
body |
Request body |
headers |
Request headers |
client_ip |
Client IP address |
timestamp |
Request timestamp |
api_audit_id |
Unique audit ID (linked to events) |
Create a .env file in the root directory:
Docker Compose (default):
DB_HOST=postgres
DB_PORT=5432
DB_USER=wallet
DB_PASS=wallet
DB_NAME=wallet
RABBITMQ_URL=amqp://guest:guest@rabbitmq:5672
RABBITMQ_EXCHANGE=wallet.events
RABBITMQ_DLX=wallet.events.dlx
ENABLE_SWAGGER=true1. Start PostgreSQL:
docker run --name wallet-pg \
-p 5432:5432 \
-e POSTGRES_USER=wallet \
-e POSTGRES_PASSWORD=wallet \
-e POSTGRES_DB=wallet \
-d postgres:162. Start RabbitMQ:
docker run --name wallet-rmq \
-p 5672:5672 \
-p 15672:15672 \
-d rabbitmq:3-management3. Start API Service:
cd services/api
npm run start:dev4. Start Worker Service:
cd services/worker
npm run start:devPre-commit Hooks (Husky + lint-staged):
- β TypeScript type checking
- β ESLint validation
- β Automatic formatting
CI/CD (GitHub Actions):
- Runs on every PR and commit
- Executes: lint β type-check β tests
- Pessimistic locking ensures wallet balance integrity
- ACID transactions for all write operations
- No negative balances enforced at database level
- Immutable event log for complete audit trail
- Event sourcing enables time-travel debugging
- Asynchronous processing for analytics and notifications
Transfer operations use the Saga pattern:
Initiated β Debited β Completed
β
Compensated β Failed
- API operations:
(requestId, walletId)uniqueness - Transfers:
requestIdonTransferEntity - Worker:
ProcessedEventEntityprevents duplicate processing
- Horizontal scaling of API and worker services
- Database connection pooling for high throughput
- Per-wallet locking allows parallel operations on different wallets
- DESIGN.md - Detailed architecture and design decisions
- Swagger UI - Interactive API documentation
- RabbitMQ Management - Message broker monitoring
This project demonstrates a production-ready event-driven wallet microservice with:
- β Strong consistency for balance updates
- β Event-driven architecture with RabbitMQ
- β Saga pattern for distributed transactions
- β Idempotency at every layer
- β Fault-tolerant background processing with DLQ
- β Real-time fraud detection and analytics
- β Comprehensive test suite with stress testing
- β Production-ready logging and monitoring