A sophisticated distributed event processing system that ensures every event is processed exactly once, even when the same event is received multiple times. Built with Redis Streams for queuing, distributed locks for concurrency safety, and a stunning real-time dashboard.
graph TB
subgraph Client["π₯οΈ Frontend (React + Vite)"]
UI[Dashboard UI]
SSE_C[SSE Client]
end
subgraph API["π API Server (Express.js)"]
GW[API Gateway]
AUTH[JWT Auth]
RL[Rate Limiter]
IDEMP[Idempotency Engine]
CTRL[Controllers]
end
subgraph Queue["π¨ Redis Streams"]
HIGH[events:high]
MED[events:medium]
LOW[events:low]
DLQ[events:dead-letter]
end
subgraph Worker["βοΈ Worker Process"]
CONSUMER[Stream Consumer]
LOCK[Distributed Lock]
HANDLER[Event Handlers]
RETRY[Retry Engine]
end
subgraph Data["πΎ Data Layer"]
PG[(PostgreSQL)]
REDIS[(Redis Cache)]
end
UI -->|HTTP/SSE| GW
GW --> AUTH --> RL --> IDEMP --> CTRL
CTRL -->|XADD| HIGH & MED & LOW
CTRL --> PG & REDIS
CONSUMER -->|XREADGROUP| HIGH & MED & LOW
CONSUMER --> LOCK --> REDIS
CONSUMER --> HANDLER
HANDLER -->|on failure| RETRY
RETRY -->|max retries| DLQ
CONSUMER --> PG
SSE_C -.->|real-time| GW
- β
Idempotency Guarantee β Every event requires an
Idempotency-Keyheader. Duplicates are detected via Redis (fast) + PostgreSQL (permanent audit) - β Redis Streams Queue β Priority-based queuing (HIGH/MEDIUM/LOW) with consumer groups
- β
Distributed Locking β
SET NX PXwith Lua-script safe release prevents concurrent processing - β
Exponential Backoff Retry β Failed events retry with
2^nsecond backoff (max 5 retries) - β Dead Letter Queue β Events exceeding max retries are quarantined with full error history
- β CRITICAL Priority Bypass β Critical events skip the queue and process synchronously
- β JWT Authentication β Secure login/register with bcrypt password hashing
- β API Key Management β Generate, list, and revoke API keys with SHA-256 hashing
- β
Sliding Window Rate Limiting β Redis sorted set-based rate limiter with
Retry-Afterheaders - β Request ID Tracing β UUID per request attached to all logs and response headers
- β Swagger/OpenAPI Docs β Auto-generated interactive API documentation
- β Live Event Feed β Server-Sent Events (SSE) for real-time updates
- β Webhook Simulator β Prove idempotency by sending N duplicate events
- β Metrics & Charts β Throughput, processing times, error rates, queue depth
- β Event Inspector β JSON payload viewer, retry timeline, cURL generator
- β DLQ Management β Replay, bulk replay, or discard dead events
- β Docker Compose β One command to run the entire stack
- β Graceful Shutdown β Drain queues on SIGTERM
- β Structured Logging β Winston with JSON format and request tracing
- β Health Checks β PostgreSQL + Redis connectivity monitoring
- β Environment Validation β envalid ensures all required config is present
- Docker & Docker Compose
- Node.js 18+ (for local development)
# 1. Clone & enter the project
git clone <your-repo-url> && cd idempotent-event-processor
# 2. Start all services
docker compose up -d
# 3. Open the dashboard
open http://localhost:5173# Start infrastructure
docker compose up -d postgres redis redis-commander
# Backend
cd backend
npm install
npx prisma migrate dev
npm run dev
# Worker (separate terminal)
cd backend
npm run worker:dev
# Frontend (separate terminal)
cd frontend
npm install
npm run dev| Method | Endpoint | Description |
|---|---|---|
POST |
/api/v1/auth/register |
Register a new user |
POST |
/api/v1/auth/login |
Login with email/password |
GET |
/api/v1/auth/profile |
Get current user profile |
POST |
/api/v1/events |
Ingest a new event (requires Idempotency-Key header) |
GET |
/api/v1/events |
List events with filters & pagination |
GET |
/api/v1/events/:id |
Get event details with retry history |
POST |
/api/v1/events/:id/replay |
Replay an event with new idempotency key |
GET |
/api/v1/events/stream |
Real-time SSE event stream |
GET |
/api/v1/events/export |
Export events as CSV |
GET |
/api/v1/dlq |
List dead letter events |
POST |
/api/v1/dlq/:id/replay |
Replay a dead event |
POST |
/api/v1/dlq/bulk-replay |
Bulk replay dead events |
DELETE |
/api/v1/dlq/:id |
Discard a dead event |
POST |
/api/v1/simulate/webhook |
Simulate duplicate webhooks |
GET |
/api/v1/metrics |
System metrics & health |
GET |
/api/v1/api-keys |
List API keys |
POST |
/api/v1/api-keys |
Create new API key |
GET |
/health |
Health check |
GET |
/api-docs |
Swagger UI |
sequenceDiagram
participant C as Client
participant A as API Server
participant R as Redis Cache
participant P as PostgreSQL
participant Q as Queue
C->>A: POST /events (Idempotency-Key: abc-123)
A->>R: GET idempotency:abc-123
R-->>A: null (not found)
A->>P: Check idempotency_store
P-->>A: null (not found)
A->>P: INSERT event
A->>Q: XADD to stream
A->>R: SETEX idempotency:abc-123 (TTL: 24h)
A->>P: INSERT idempotency_store
A-->>C: 201 Created
Note over C,Q: Same request arrives again...
C->>A: POST /events (Idempotency-Key: abc-123)
A->>R: GET idempotency:abc-123
R-->>A: cached response β
A-->>C: 200 OK + X-Idempotent-Replayed: true
ββββββββββββββββ ββββββββββββββββββββ βββββββββββββββββ
β users β β events β β retry_logs β
ββββββββββββββββ€ ββββββββββββββββββββ€ βββββββββββββββββ€
β id (UUID) β β id (UUID) βββββββ id (UUID) β
β email β β idempotencyKey β β eventId (FK) β
β passwordHash β β type β β attemptNumber β
β name β β payload (JSONB) β β attemptedAt β
β createdAt β β metadata (JSONB) β β error β
ββββββββ¬ββββββββ β status β β nextRetryAt β
β β priority β βββββββββββββββββ
β β retryCount β
ββββββββ΄ββββββββ β processingTimeMs β βββββββββββββββββ
β api_keys β β errorMessage β β alerts β
ββββββββββββββββ€ β createdAt β βββββββββββββββββ€
β id (UUID) β ββββββββββ¬ββββββββββ β id (UUID) β
β userId (FK) β β β eventId (FK) β
β name β ββββββββββ΄ββββββββββ β type β
β keyHash β βidempotency_store β β message β
β rateLimit β ββββββββββββββββββββ€ β severity β
β expiresAt β β key (PK) β β createdAt β
β isActive β β eventId (FK) β βββββββββββββββββ
ββββββββββββββββ β responsePayload β
β expiresAt β
ββββββββββββββββββββ
βββ backend/
β βββ src/
β β βββ controllers/ # Request handlers
β β βββ handlers/ # Event type processors
β β βββ middleware/ # Auth, rate limit, idempotency
β β βββ routes/ # Express routes with Swagger docs
β β βββ services/ # Business logic (queue, lock, metrics)
β β βββ utils/ # Logger, Redis, Prisma, config
β β βββ app.js # Express configuration
β β βββ server.js # API server entry
β β βββ worker.js # Worker process entry
β βββ prisma/
β β βββ schema.prisma # Database schema
β βββ Dockerfile
βββ frontend/
β βββ src/
β β βββ components/ # Layout, charts, UI
β β βββ hooks/ # useEvents, useMetrics, useSSE
β β βββ lib/ # API client, auth context, utils
β β βββ pages/ # All 9 dashboard pages
β βββ Dockerfile
βββ docker-compose.yml # 6 services orchestration
βββ .env # Environment configuration
βββ README.md
| Layer | Technology | Purpose |
|---|---|---|
| Runtime | Node.js 20 | Server-side JavaScript |
| API | Express.js 4 | HTTP framework |
| Database | PostgreSQL 16 | Persistent event storage |
| Cache/Queue | Redis 7 | Caching, streams, locks, rate limiting |
| ORM | Prisma | Type-safe database access |
| Queue | Redis Streams | Priority-based event queuing |
| Auth | JWT + bcrypt | Token-based authentication |
| Validation | Zod | Runtime schema validation |
| Logging | Winston | Structured logging |
| Docs | Swagger/OpenAPI | Auto-generated API documentation |
| Frontend | React 18 + Vite | Dashboard UI |
| Styling | Tailwind CSS 3 | Utility-first CSS |
| Charts | Recharts | Data visualization |
| Animation | Framer Motion | Smooth UI transitions |
| Container | Docker Compose | Multi-service orchestration |
| Service | Port | Description |
|---|---|---|
| API Server | 3000 | Express.js backend |
| Worker | β | Background event processor |
| Frontend | 5173 | React dashboard |
| PostgreSQL | 5432 | Primary database |
| Redis | 6379 | Cache, queue, locks |
| Redis Commander | 8081 | Redis debug GUI |
MIT
Built with β€οΈ as a portfolio project demonstrating distributed systems, event-driven architecture, and idempotent processing patterns.