Production Readiness
Use this checklist to take a Glasswork service from "it runs locally" to "safe in production". Skim top-to-bottom on first deploy; revisit when adding new modules.
Quick Checklist
- ✅ Disable public docs:
openapi.serveSpecs = false,openapi.serveUI = false - ✅ Turn on rate limiting:
rateLimit.enabled = true, DynamoDB store in prod - ✅ Lock down CORS: explicit origins + credentials only if required
- ✅ Secure headers: enable
middleware.secureHeaders - ✅ Authentication: implement middleware; never rely on
publicflag alone - ✅ Secrets from env: load from SSM/Secrets Manager; never commit secrets
- ✅ Structured logging: Pino JSON with requestId + service names
- ✅ Exception tracking: CloudWatch tracker or Sentry/AppSignal
- ✅ TLS everywhere: HTTPS and HSTS at CDN/ALB/API Gateway
- ✅ Database hygiene: pool sizing, connection reuse, migrations applied
- ✅ Email: out of SES sandbox; verified sender identities
Not on Lambda?
This checklist assumes Lambda. For containers/Kubernetes:
- Keep health/readiness endpoints enabled
- Size connection pools for pod concurrency (not Lambda)
- Replace Function URL/CORS guidance with your ingress settings
- Skip provisioned concurrency/SnapStart notes
Essentials (Before Traffic)
1. Secure Surface
OpenAPI exposure:
const { app } = await bootstrap(AppModule, {
openapi: {
enabled: true,
serveSpecs: false, // Don't expose in production
serveUI: false,
},
});Keep writeToFile if you need to publish specs to an artifact store or gateway.
Rate limiting & CORS:
const { app } = await bootstrap(AppModule, {
rateLimit: {
enabled: true,
storage: 'dynamodb',
windowMs: 60_000,
maxRequests: 100,
dynamodb: {
tableName: process.env.RATE_LIMIT_TABLE!,
region: process.env.AWS_REGION,
},
},
middleware: {
cors: {
origin: ['https://app.example.com'],
credentials: true,
},
secureHeaders: true,
},
});The DynamoDB table needs a string partition key named bucketId and TTL on expiresAt. The limiter uses conditional updates so concurrent requests cannot overrun the configured maximum. Storage errors fail open to preserve API availability, so monitor limiter errors and keep defense-in-depth controls on login and other abuse-sensitive endpoints.
Glasswork reads API Gateway/Lambda requestContext source IPs directly. Behind another runtime adapter, set keyGenerator to a trusted client identifier. Set trustProxy: true only when the edge overwrites forwarded-IP headers.
2. Authentication & Authorization
- Implement auth middleware;
public: trueonly marks docs as unauthenticated. - Document auth scheme in OpenAPI and verify 401/403 responses are present.
- Prefer short-lived access tokens and server-side sessions.
- Strip sensitive headers from logs.
3. Configuration & Secrets
- Set
NODE_ENV=production; run with"type": "module"and strict TS build. - Load secrets from env/SSM/Secrets Manager; never hardcode.
- Validate configuration via
createConfigat startup. - Default to least privilege IAM roles; restrict SES identities and S3 buckets.
4. Health & Readiness (Container Deployments)
Lambda Note
Health endpoints are primarily for container/server deployments (ECS, Kubernetes, ALB). Lambda doesn't need them. AWS manages instance health automatically.
For container deployments:
- Add a cheap, dependency-light endpoint (e.g.
/internal/health). - Exclude it from OpenAPI with
openapi: { exclude: true }on the route. - Optionally add a deeper readiness check that touches DB/queues.
5. Observability
Logging:
- Use
pinowith the providedlambdaPinoConfig. - Prefer
createContextAwarePinoLoggerin services for consistent fields. - Ship requestId + service name in every log line.
- Avoid logging secrets (tokens, passwords, PII).
Error handling:
- Rely on domain exceptions (
NotFoundException,BadRequestException, etc.). - Keep a default error handler; do not leak stack traces in production responses.
- Track 5xx errors at minimum. Consider including 404s for critical resources.
Metrics:
- Track latency, 4xx/5xx rates, rate-limit hits, cold starts.
- Enable CloudWatch alarms for error rate, latency, and cold start spikes.
6. Data Safety
- Validate all input via Valibot schemas.
- Enforce response validation for external-facing routes (prevents data leaks).
- Use
strictTypes: truefor sensitive responses. - Back up production databases; enable RDS performance insights and error logs.
7. Database & Connection Management
- Size connection pools for Lambda concurrency or server threads.
- Reuse clients across invocations; avoid creating clients per request.
- For Lambda + Postgres, use PgBouncer/RDS Proxy; set low pool size.
- Run migrations before deploy; block boot if pending migrations remain.
8. Email Hygiene
- Move SES out of sandbox before production; verify sender identities.
- Set
configurationSetto emit bounces/complaints; alarm on high rates. - For dev/staging, keep sandbox on and point to non-customer mailboxes.
Deploy Safely
- Immutable builds: use esbuild with
format: 'esm',keepNames: true,external: ['@aws-sdk/*']. - Infrastructure: use CDK v2 in TypeScript; see Lambda Deployment for alternatives. Select an explicit supported Node.js runtime and set memory + timeout per workload.
- Cold starts: minimize bundle size; use provisioned concurrency for critical paths; reuse DI container.
- Static assets: serve from CDN/S3; do not serve from app.
Safety Nets Before Launch
- End-to-end smoke test (auth + one read + one write) in staging.
- Run lint, format, and tests on CI.
- Toggle feature flags via config, not code.
- Document rollback procedure (last known good build + infra change).
- Set timeouts: HTTP clients, DB queries, and Lambda function timeout.
- Use idempotency where appropriate for background jobs and webhooks.
Optional But Valuable
- Security: Content Security Policy headers; JWT/session rotation; audit logging.
- Operational: request sampling for logs; structured logging only (no
console.logdumps). - Data: soft deletes for key tables; migrations with down scripts.
Adding Module Features
When adding new modules (background jobs, caching, auth, CLI, multi-tenancy), document:
- How it changes deployment (queues, cache, roles).
- Observability knobs (metrics/logs).
- Failure modes and rollbacks.
Learn More
- Observability Guide - Logging and metrics setup
- OpenAPI Guide - Lock in your API surface
- Testing Guide - Add robust tests
- Lambda Deployment - Optimize for serverless
