Bun + TypeScript + PostgreSQL (Neon) + Redis
┌─────────────────────────────────────────────┐
│ CLIENT LAYER │
│ API Key Auth + Rate Limiting (Redis) │
└──────────────────┬──────────────────────────┘
│
┌──────────────────▼──────────────────────────┐
│ MIDDLEWARE PIPELINE │
│ Zod Validation → Auth → Rate Limit → PCI │
└──────────────────┬──────────────────────────┘
│
┌────────────────────────────┼────────────────────────────┐
│ │ │
┌─────────▼──────────┐ ┌─────────────▼──────────────┐ ┌────────▼────────┐
│ PAYMENT SERVICE │ │ FRAUD DETECTION │ │ WEBHOOKS │
│ │ │ │ │ │
│ ┌──────────────┐ │ │ Velocity Check (Redis ZSET)│ │ Outbox Pattern │
│ │ Idempotency │ │ │ Amount Threshold │ │ (PostgreSQL) │
│ │ (PostgreSQL) │ │ │ Source Reputation │ │ │
│ └──────┬───────┘ │ │ Customer Blocking (PG) │ │ Exponential │
│ │ │ └────────────────────────────┘ │ Backoff+Jitter │
│ ┌──────▼───────┐ │ │ │
│ │ State Machine│ │ │ HMAC-SHA256 │
│ │ (PG Transact)│ │ │ Signatures │
│ └──────┬───────┘ │ └────────┬────────┘
│ │ │ │
│ ┌──────▼───────┐ │ ┌────────▼────────┐
│ │ Ledger │ │ │ Dispatcher │
│ │ (Double- │ │ │ (Background │
│ │ Entry, PG) │ │ │ Worker) │
│ └──────────────┘ │ └─────────────────┘
└────────────────────┘
┌─────────────────────────────────────────────────────────────────────────────┐
│ STORAGE LAYER │
│ │
│ ┌─────────────────────────────┐ ┌──────────────────────────────────┐ │
│ │ PostgreSQL (Neon) │ │ Redis │ │
│ │ │ │ │ │
│ │ Payments (ACID) │ │ Distributed Locks (Lua CAS) │ │
│ │ Ledger Entries │ │ Rate Limit Sliding Window │ │
│ │ Idempotency Keys │ │ Fraud Velocity Tracking (ZSET) │ │
│ │ Webhook Outbox │ │ API Key Cache │ │
│ │ Blocked Customers │ │ Circuit Breaker State │ │
│ └─────────────────────────────┘ └──────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────────────────┘
| Pattern | Problem | Implementation |
|---|---|---|
| Idempotency Keys | Duplicate requests on retry | PostgreSQL upsert with unique constraint |
| Atomic State Machine | Race conditions on status updates | SELECT ... FOR UPDATE in PG transaction |
| Double-Entry Ledger | Financial traceability | Atomic CTE: compute balance → insert → return |
| Distributed Lock | Concurrent payment processing | Redis SET NX EX + Lua CAS release |
| Sliding Window Rate Limit | API abuse | Redis ZSET + ZREMRANGEBYSCORE |
| Velocity Fraud Detection | Stolen card patterns | Redis ZSET time-windowed counter |
| Outbox Pattern | Lost webhook events | PG transactional write → async dispatch |
| Exponential Backoff + Jitter | Thundering herd on retries | min(1000 * 2^attempts, 30s) + jitter |
| Circuit Breaker | Cascading downstream failures | Closed → Open → Half-Open state machine |
| PCI Security Headers | Compliance | Strict-Transport-Security, X-Content-Type-Options |
-- Payment: core entity with optimistic locking via version column
Payment (id, idempotencyKey UNIQUE, status ENUM, amount, currency,
customerId, paymentMethod, metadata JSONB, version, timestamps)
-- Ledger: double-entry bookkeeping with computed running balance
LedgerEntry (id, paymentId FK, type ENUM, account, amount,
currency, balanceAfter, createdAt)
-- Idempotency: request deduplication
IdempotencyKey (key PK, paymentId, status, response JSONB, createdAt)
-- Webhooks: outbox pattern for reliable delivery
WebhookEvent (id, type, payload JSONB, status, attempts,
createdAt, lastAttemptAt, nextRetryAt)
-- Fraud: blocked customer registry
BlockedCustomer (customerId PK, reason, blockedAt, expiresAt)# Clone and install
git clone <repo-url> && cd payment-gateway
bun install
# Configure
cp .env.example .env
# Edit .env with your DATABASE_URL and REDIS_URL
# Push schema to PostgreSQL
bun run db:push
# Start server
bun run dev
# Run the full pipeline demo
bun run pipelineAll endpoints require Authorization: Bearer sk_test_demo_key_00000000000000000000
# Health check (no auth required)
curl http://localhost:3000/health
# Create a payment
curl -X POST http://localhost:3000/v1/payments \
-H "Content-Type: application/json" \
-H "Authorization: Bearer sk_test_demo_key_00000000000000000000" \
-d '{
"idempotencyKey": "idem_unique_123",
"amount": 5000,
"currency": "USD",
"customerId": "cust_001",
"paymentMethod": "card"
}'
# Get payment status
curl http://localhost:3000/v1/payments/{id} \
-H "Authorization: Bearer sk_test_demo_key_00000000000000000000"
# Refund a payment
curl -X POST http://localhost:3000/v1/payments/{id}/refund \
-H "Content-Type: application/json" \
-H "Authorization: Bearer sk_test_demo_key_00000000000000000000" \
-d '{ "amount": 2500 }'
# Prometheus metrics (no auth required)
curl http://localhost:3000/metricsbun run pipeline # 7 pipelines, 16 stages — see the full flow
bun run showcase # Race conditions, attack simulation, refunds
bun run benchmark # 1000 concurrent payments throughput test
bun run demo # 12-step feature walkthroughsrc/
├── config/ Environment variables, production guards
├── lib/
│ ├── redis.ts Redis connection singleton
│ ├── prisma.ts PostgreSQL client (Neon + Prisma 7)
│ ├── distributed-lock.ts Redis lock with Lua CAS release
│ ├── circuit-breaker.ts Failure detection + recovery
│ ├── metrics.ts Prometheus counters + histograms
│ └── logger.ts Structured JSON logging (pino)
├── middleware/
│ ├── api-key.ts Bearer token authentication
│ ├── rate-limit.ts Sliding window (Redis ZSET)
│ ├── validation.ts Zod schema validation
│ ├── security.ts PCI compliance headers
│ └── errors.ts Typed error codes
├── modules/
│ ├── payment/
│ │ ├── state-machine.ts Atomic status transitions (PG tx)
│ │ ├── idempotency.ts Request deduplication
│ │ └── payment-service.ts Orchestration layer
│ ├── ledger/
│ │ └── ledger.ts Double-entry with atomic balance
│ ├── fraud/
│ │ └── fraud.ts Velocity + amount + source checks
│ └── webhook/
│ ├── outbox.ts PG-backed event queue
│ └── dispatcher.ts HMAC-signed delivery
├── index.ts Server entry point
└── worker.ts Background webhook processor
| Layer | Technology | Why |
|---|---|---|
| Runtime | Bun | 4x faster startup, native TypeScript, built-in test runner |
| Language | TypeScript (strict) | Type safety, better DX, self-documenting |
| Database | PostgreSQL (Neon) | ACID transactions, JSONB, ENUM types, foreign keys |
| ORM | Prisma 7 | Type-safe queries, migrations, introspection |
| Cache/Queue | Redis | Sub-ms latency, Lua scripts, sorted sets |
| Validation | Zod | Runtime + compile-time type safety |
| Logging | pino | Structured JSON, fast, child loggers |
| IDs | nanoid | URL-safe, collision-resistant, 21 chars |
MIT