Actionable rules for designing, coding, deploying and operating TypeScript-based microservices running on AWS Lambda and Kubernetes with event-driven patterns.
Stop fighting distributed systems complexity. These Cursor Rules transform your TypeScript development into a production-ready microservices powerhouse that handles scale, fault tolerance, and rapid deployment cycles.
You know the drill: start with good intentions for clean microservices architecture, then six months later you're debugging cascade failures across 20 services, dealing with database coupling nightmares, and your deployment takes 3 hours because everything breaks differently in production.
The common pain points that kill productivity:
These Cursor Rules implement battle-tested patterns from high-scale distributed systems. They enforce domain-driven design, event-driven architecture, and infrastructure-as-code practices that prevent common microservices pitfalls before they happen.
What makes this different: Instead of generic microservices advice, these rules provide specific TypeScript implementations, AWS Lambda optimizations, and Kubernetes deployment patterns that work at enterprise scale.
Before: Spending 2-3 days setting up a new microservice with proper error handling, logging, deployment scripts, and database patterns.
After: Run cursor with these rules and get:
// Auto-generated service structure with domain separation
/src
/domain // Pure business logic, zero infrastructure dependencies
/handlers // Lambda handlers with middleware pre-configured
/adapters // Database/external service interfaces
/types // Shared type definitions with barrel exports
The rules enforce clean architecture automatically - your domain layer can't accidentally import infrastructure code because the linter prevents it.
Before: Manually implementing event publishing, dealing with message ordering, duplicate processing, and schema evolution headaches.
After: Get standardized event patterns:
// Rules generate this pattern automatically
export async function createOrder(cmd: CreateOrderCmd, deps: Deps): Promise<OrderCreatedEvt> {
assertValid(cmd);
const id = uuid();
await deps.repo.save({ id, ...cmd });
return { type: "OrderCreated", payload: { id, ...cmd } };
}
Built-in outbox pattern, schema versioning, and idempotent consumers eliminate the usual event-driven pitfalls.
Before: Custom deployment scripts per service, inconsistent environment handling, manual canary deployments, and debugging production issues without proper observability.
After: Infrastructure-as-code with every service:
.cursor-rules in your project root// Cursor will guide you to this clean structure
interface CreateUserCmd {
email: string;
name: string;
}
interface UserCreatedEvt {
type: "UserCreated";
payload: { id: string; email: string; name: string };
}
// Domain logic stays pure - no infrastructure concerns
export async function createUser(
cmd: CreateUserCmd,
deps: { repo: UserRepo; eventBus: EventBus }
): Promise<UserCreatedEvt> {
assertValid(cmd);
const id = uuid();
const user = { id, ...cmd };
await deps.repo.save(user);
await deps.eventBus.publish({
type: "UserCreated",
payload: user
});
return { type: "UserCreated", payload: user };
}
The rules include complete CI/CD patterns:
Built-in observability patterns give you:
These rules transform microservices development from a complex architectural challenge into a predictable, productive workflow. You'll spend time building features instead of fighting distributed systems complexity.
The investment in setting up these patterns pays dividends immediately - your first service deployment will be faster and more reliable than your previous manual approaches. Your second service will feel effortless.
You are an expert in TypeScript, Node.js, AWS Lambda, Serverless Framework, Docker, Kubernetes, Apache Kafka, Amazon EventBridge/SNS, CQRS, and Event Sourcing.
Key Principles
- Design around business capabilities (DDD) and enforce the Single Responsibility Principle at service level.
- Prefer stateless, independently deployable microservices. Never share a database schema across services.
- Favor event-driven, asynchronous communication to reduce coupling; fall back to REST/gRPC only for request/response needs.
- Treat infrastructure as code (IaC): version CloudFormation/Terraform/Helm charts alongside application code.
- Everything is code-reviewable, buildable, testable, reproducible.
- Automate: CI runs lint → unit tests → integration tests → build → security scan → package → deploy.
TypeScript
- Enable `"strict": true` and `"noImplicitAny": true` in `tsconfig.json`.
- Use ES modules (`import/export`) only. Disallow `require` except in migration code.
- All public types live in `/src/types`. Expose with `index.ts` barrels.
- Enforce functional style: pure functions first; use classes only for aggregating domain invariants.
- Naming:
• Variables: `camelCase` (e.g., `userId`, `paymentToken`).
• Types & Interfaces: `PascalCase` prefixed with `I` only for external DTOs (`IUserDTO`).
• Folders: `kebab-case` (`payment-service`, `order-handler`).
- Domain layer must not import from infrastructure layer (`src/domain` → no imports from `src/adapters`). Use dependency inversion.
- Example function skeleton:
```ts
export async function createOrder(cmd: CreateOrderCmd, deps: Deps): Promise<OrderCreatedEvt> {
assertValid(cmd);
const id = uuid();
await deps.repo.save({ id, ...cmd });
return { type: "OrderCreated", payload: { id, ...cmd } };
}
```
Error Handling & Validation
- Validate inputs at API edge (Lambda handler) with Zod or Joi; domain layer assumes validity.
- Return early on error, never nest more than two `if` levels.
- Use structured error objects `{ code, message, details? }`. Map to HTTP status in API Gateway.
- Implement resilience patterns:
• Circuit Breaker (e.g., `opossum`) wraps network calls.
• Retry with exponential back-off (3 attempts max) for idempotent operations.
• Bulkhead: isolate thread pools.
- Health checks: `/health/live` (is process up?) and `/health/ready` (deps reachable?). For Lambda, expose via Lambda extension or custom metric.
AWS Lambda & Serverless Framework
- One Lambda = One bounded context operation (e.g., `order-create`). Avoid fat Lambdas.
- Handlers live in `/src/handlers/<operation>.handler.ts` and export a single async function.
- Always set `memorySize` and `timeout` explicitly; start with 256 MB & 15 s.
- Use AWS SDK v3 modular imports (`@aws-sdk/client-dynamodb`) to minimize cold start size.
- Environment variables only for non-secret config (stage, log level). Secrets via AWS SM/Secrets Mgr.
- Wrap handler with middleware (middy):
```ts
export const handler = middy(coreHandler)
.use(jsonBodyParser())
.use(inputOutputLogger())
.use(httpErrorHandler());
```
- Version your APIs; deploy through stages (`dev`, `qa`, `prod`). Canary deployments: `stage: prod`, `percentage: 5`.
Docker & Kubernetes (for stateful or long-running services)
- Base image: `public.ecr.aws/bitnami/node:18-prod`. Multi-stage build: builder → slim runtime.
- Each image MUST expose non-root UID (`node`) and `HEALTHCHECK`.
- Helm chart layout:
• `/charts/<service>/values.yaml` – config only.
• `/charts/<service>/templates/*.yaml` – no hard-coded stage values.
- Readiness probe hits `/health/ready`. Liveness probe hits `/health/live`.
- Resources: request = average, limit ≤ 2× request. Autoscale via HPA on `cpu` and custom latency metric.
Messaging & Event-Driven Rules
- Topic naming: `<domain>.<event>` (e.g., `order.created`). Use kebab-case for Kafka topics.
- Events are immutable and schema-versioned. Store Avro/JSON Schema in Schema Registry; include `schemaVersion` field.
- Prefer at-least-once delivery; make consumers idempotent (dedup via event ID + processed-at timestamp).
- Implement outbox pattern for transactional publish.
- CQRS:
• Command = imperative, returns void/ack.
• Query = side-effect-free read.
Testing & Deployment
- Unit tests in `/__tests__` with Jest. Coverage ≥ 90 % lines.
- Contract tests per API using Pact; provider verifies before promotion.
- Integration tests spin up localstack + docker-compose Kafka.
- Deploy pipeline:
1. PR merge → Build & test.
2. Push image to ECR or package Lambda.
3. Deploy to dev.
4. Run smoke tests.
5. Automated canary to prod → 5 % traffic → 0 errors & < p95 *1.2* baseline for 30 min → 100 %.
Performance & Observability
- Enable X-Ray tracing; propagate `trace-id` through async hops (Kafka headers).
- Log in JSON (`ts`, `level`, `msg`, `service`, `reqId`, `userId`?). One line per event.
- Metrics: Emit custom CloudWatch `Latency`, `ColdStart`, `DLQDepth`. For k8s: Prometheus scrape `/metrics`.
- Cache read-heavy Lambda responses with API Gateway cache or DynamoDB DAX.
Security
- Enforce least privilege IAM; each service gets its own role.
- Use JWT/OIDC; validate in API Gateway/Lambda authorizer, not inside handlers.
- Enable AWS WAF on API Gateway; rate limit by IP/user.
- Run `npm audit` & `trivy fs image` in CI.
- Encrypt data at rest (KMS) and in transit (TLS 1.2+).
Additional Guidelines
- Versioning: Semantic version for services; API deprecation policy = 6 months.
- Documentation: Autogenerate OpenAPI & ADRs; store in `/docs` and publish to portal.
- Timeouts: Downstream timeout < caller timeout < API GW timeout.
- Never expose internal service names/URLs; use API Gateway or service mesh (Istio) for ingress/egress.