docker-compose up --buildcurl -X POST http://localhost:3000/accounts/register \
-H "Content-Type: application/json" \
-d '{
"account_name": "Test Co",
"monthly_limit": 10000,
"webhook_url": "https://example.com/webhook"
}'Save the returned api_key value.
API_KEY="sk_..."
curl -X POST http://localhost:3000/emails/send \
-H "Authorization: Bearer $API_KEY" \
-H "Content-Type: application/json" \
-d '{
"to": "test@example.com",
"subject": "Test Email",
"html": "<p>This is a test</p>",
"idempotency_key": "test-1"
}'Save the returned email_id.
EMAIL_ID="..."
curl http://localhost:3000/emails/$EMAIL_ID \
-H "Authorization: Bearer $API_KEY"curl http://localhost:3000/accounts/usage \
-H "Authorization: Bearer $API_KEY"curl http://localhost:3000/healthReturns 200 if everything is ok.
✅ Email Reliability
- Idempotency prevents duplicates (same request = same email)
- 5 automatic retries on send failure
- Append-only billing (charge only on success)
✅ Webhooks
email.sent- Triggered when email deliveredemail.failed- Triggered after all retries exhausted- 3 retries with exponential backoff
✅ Rate Limiting
- 100 requests/minute per account
- X-RateLimit-* headers in responses
✅ Security
- Cryptographically secure API keys
- Account-scoped access (can't see others' emails)
- Input validation on all endpoints
✅ Resilience
- Automatic database reconnection
- Service health checks
- Graceful shutdown
src/config/env.ts ← Configuration validation
src/db/index.ts ← Database connection & health
src/db/schema.sql ← Database tables
src/middleware/apiKeyAuth.ts ← Bearer token auth
src/middleware/rateLimit.ts ← Request rate limiting
src/routes/accounts.ts ← Account & API key endpoints
src/routes/emails.ts ← Email endpoints
src/services/usageService.ts ← Billing tracking
src/workers/emailWorker.ts ← Background email processor
src/app.ts ← Express setup
src/server.ts ← Server startup/shutdown
tests/integration.test.ts ← Integration tests
# Build TypeScript
npm run build
# Start production server
npm start
# Start development with auto-reload
npm run dev
# Run integration tests
npm test
# Docker commands
docker-compose up --build # Start all services
docker-compose logs -f api # Watch API logs
docker-compose logs -f postgres # Watch database logs
docker-compose logs -f redis # Watch cache logs
docker-compose down # Stop all services| Code | Meaning |
|---|---|
| 200 | Success |
| 201 | Created |
| 202 | Accepted (email queued) |
| 400 | Bad request (invalid input) |
| 401 | Unauthorized (missing/invalid API key) |
| 404 | Not found (email doesn't exist) |
| 429 | Too many requests (rate limited) |
| 503 | Service unavailable (database down) |
-- Accounts (with webhook support)
accounts (id, account_name, webhook_url, monthly_limit, created_at)
-- API Keys
api_keys (id, account_id, key_hash, key_prefix, created_at)
-- Emails
emails (id, account_id, to, subject, html, status, attempts,
error_details, provider_message_id, created_at, sent_at)
-- Usage tracking (append-only)
email_usage (id, account_id, month, email_count, created_at)NODE_ENV=production
PORT=3000
DATABASE_URL=postgresql://user:password@postgres:5432/mail
REDIS_URL=redis://redis:6379
RESEND_API_KEY=re_xxxxxxxxxxxx┌─────────────┐
│ Client │
└──────┬──────┘
│ HTTP
▼
┌──────────────────────────────┐
│ Express API Server │
│ ├─ Request ID Tracing │
│ ├─ API Key Auth │
│ ├─ Rate Limiting │
│ └─ Error Handling │
└──────┬──────────────────┬────┘
│ │
▼ SQL ▼ Commands
┌─────────────┐ ┌──────────────┐
│ PostgreSQL │ │ Redis Queue │
│ Database │ │ (BullMQ) │
└─────────────┘ └──────┬───────┘
│ Process Jobs
▼
┌──────────────────┐
│ Email Worker │
│ ├─ Send (5x) │
│ ├─ Webhook (3x) │
│ └─ Record Usage │
└──────┬───────────┘
│ HTTP POST
▼
┌──────────────────┐
│ Resend Provider │
│ + Customer │
│ Webhooks │
└──────────────────┘
curl http://localhost:3000/health
# Returns database and service health statusdocker-compose ps
# Shows health status for each service
# HEALTHY = all dependencies responding# All services
docker-compose logs -f
# Specific service
docker-compose logs -f api
docker-compose logs -f postgres
docker-compose logs -f redis
# Last N lines
docker-compose logs --tail=100- Check PostgreSQL is running:
docker-compose ps - Check DATABASE_URL is correct in .env
- Wait 30s for database to initialize
- Check Redis is running:
docker-compose ps - Check REDIS_URL is correct in .env
- Account is over 100 requests/minute
- Check X-RateLimit-Reset header for next available time
- Email ID doesn't exist
- Email belongs to different account
- Check email was successfully sent (got 202 response)
- Check 'to' field is valid email address
- Check 'subject' and 'html' are not empty
- Set RESEND_API_KEY environment variable
- Update DATABASE_URL to production database
- Update REDIS_URL to production Redis
- Update webhook_url in account registration
- Test health endpoint responds 200
- Monitor logs for errors
- Set NODE_ENV=production
- Configure auto-restart policies
- Setup log aggregation
- Setup monitoring/alerting
- Default: 100 requests/minute per account
- Header: X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset
- Retry: Use Retry-After header when 429 received
For detailed documentation, see IMPLEMENTATION_SUMMARY.md