Twój serwer Express działa lokalnie, ale w chwili, gdy uderza w niego prawdziwy ruch, obsługa błędów nie istnieje, połączenia z bazą danych wyciekają, a nikt nie pomyślał o rate limitingu. Te przepisy to naprawiają — każdy prompt produkuje zahartowany produkcyjnie kod Node.js, który radzi sobie z problemami świata rzeczywistego pomijanymi przez tutoriale.
Prompty na scaffolding API z prawidłowym middleware, walidacją i obsługą błędów
Przepisy na integrację z bazą danych z poolingiem połączeń i migracjami
Wzorce uwierzytelniania z odświeżaniem JWT i RBAC
Przepisy na testy i wdrożenie pod kątem gotowości produkcyjnej
Notatka
Te prompty są niezależne od narzędzia: wklej je identycznie do trybu agenta Cursor, Claude Code (claude "<prompt>" lub interaktywnie) albo Codex (codex "<prompt>", rozszerzenie IDE czy zadanie Cloud na worktree). Output i kroki oceny są takie same — różni się tylko miejsce, w którym piszesz. Tam, gdzie przepis dotyka bazy danych lub zewnętrznego API, poniższe notki MCP/skills pokazują, jak zacieśnić pętlę.
Scenariusz: Zaczynasz nowy serwis i potrzebujesz struktury projektu, która skaluje się ponad 10 tras, nie stając się niemożliwą do utrzymania.
Wskazówka
Create a Node.js TypeScript project with Express following clean architecture. Structure: src/domain/ for entities and repository interfaces, src/application/ for use cases, src/infrastructure/ for database adapters, external API clients, and Express configuration, src/presentation/ for route handlers, DTOs, and middleware. Include: tsconfig with strict mode and path aliases (@domain, @application, @infrastructure, @presentation), ESLint with TypeScript rules, Vitest for testing, dependency injection using tsyringe with a container setup file. Create a health check endpoint at GET /health that returns { status: 'ok', timestamp, uptime }. Add graceful shutdown handling: listen for SIGTERM and SIGINT, close the HTTP server, drain database connections, then exit. Write the health check test.
Oczekiwany output: Scaffold projektu z architekturą czterowarstwową, kontener DI, health check, graceful shutdown i testy.
Scenariusz: Potrzebujesz API użytkowników z porządną walidacją wejścia, spójnymi odpowiedziami błędów i typowanymi ciałami request/response.
Wskazówka
Create a complete CRUD API for a users resource at /api/v1/users. Use Zod schemas for request validation: createUserSchema (name required 2-100 chars, email required and valid, password min 8 chars with complexity regex, role enum user/admin), updateUserSchema (all fields optional, partial of create). Create a validate(schema) middleware that validates req.body and returns 422 with field-level errors in the format { errors: [{ field: 'email', message: 'Invalid email format' }] }. Create a global error handler middleware that catches: ValidationError (422), NotFoundError (404), ConflictError (409), UnauthorizedError (401), and unknown errors (500 with generic message in production, full stack in development). Every handler should use async/await with a catchAsync wrapper that forwards errors to next(). Response format: { data: T } for success, { error: { code, message, details? } } for errors. Write integration tests using supertest for every endpoint and error case.
Oczekiwany output: Route handlery, schematy Zod, middleware walidacji, error handler, narzędzie catchAsync i testy supertest.
Scenariusz: Twoje API potrzebuje uwierzytelniania, które nie zmusza użytkowników do ponownego logowania co 15 minut, ale też nie używa długożyjących tokenów.
Wskazówka
Implement JWT authentication with refresh token rotation. (1) Login endpoint POST /api/auth/login: validate credentials against bcrypt hash, generate a short-lived access token (15 minutes) with userId and role claims, generate a refresh token (30 days) stored as a hashed value in the database with a family ID for rotation detection. Return both tokens. (2) Refresh endpoint POST /api/auth/refresh: validate the refresh token, check it has not been revoked, issue new access + refresh tokens, invalidate the old refresh token. If a revoked refresh token is reused, invalidate ALL tokens in that family (theft detection). (3) Auth middleware: extract Bearer token from Authorization header, verify JWT signature and expiration, attach user to req.user. (4) Logout endpoint POST /api/auth/logout: revoke the refresh token family. (5) Password reset flow: POST /api/auth/forgot-password generates a time-limited token sent via email, POST /api/auth/reset-password validates token and updates password. Test token rotation, theft detection, and expiration handling.
Oczekiwany output: Trasy auth, narzędzia JWT, middleware auth, model refresh tokena i testy bezpieczeństwa.
Scenariusz: Twoje publiczne API jest masakrowane przez scrapery, a ty nie masz żadnej ochrony przed nadużyciami.
Wskazówka
Implement multi-layer rate limiting. (1) Global rate limiter using express-rate-limit with Redis store (for multi-instance): 100 requests per minute per IP. Return 429 with Retry-After header and JSON error body. (2) Per-endpoint limits: POST /api/auth/login at 5 attempts per 15 minutes per IP (brute force protection), POST /api/auth/forgot-password at 3 per hour per email, POST /api/*/upload at 10 per hour per user. (3) Sliding window rate limiter for API keys: read the plan from the user record (free: 100/hour, pro: 1000/hour, enterprise: 10000/hour), track usage in Redis sorted sets with millisecond precision, return X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset headers on every response. (4) Create a rateLimiter({ points, duration, keyGenerator }) factory function for reusable limit configurations. Test rate limit enforcement, header values, and Redis key cleanup.
Oczekiwany output: Fabryka rate limitera, integracja z Redis store, konfiguracje per-endpoint, nagłówki odpowiedzi i testy.
Scenariusz: Twoje zapytania do bazy są rozsiane wszędzie bez poolingu połączeń, bez transakcji, a migracje uruchamiasz ręcznie.
Wskazówka
Set up Prisma ORM for a PostgreSQL database in this Node.js project. (1) Define the schema in prisma/schema.prisma: User (id uuid, email unique, name, hashedPassword, role, createdAt, updatedAt), Product (id uuid, name, slug unique, description, price Decimal, stock Int, categoryId, createdAt), Order (id uuid, userId, status enum pending/paid/shipped/delivered/cancelled, total Decimal, createdAt), OrderItem (orderId, productId, quantity, unitPrice, composite key). (2) Create a singleton Prisma client in src/infrastructure/database.ts with query logging in development and connection pool configuration (min 2, max 10). (3) Write a transaction pattern for order creation: createOrder(userId, items[]) that validates stock for each item, decrements stock, creates the order and items, and calculates the total — all in a single transaction that rolls back if any item is out of stock. (4) Create a seed script with realistic data using Faker. (5) Add a migration script that generates and applies migrations. Test the transaction rollback behavior when stock is insufficient.
Oczekiwany output: Schemat Prisma, singleton klienta, wzorce transakcji, skrypt seed i testy transakcji.
Notatka
Dodaj serwer Postgres MCP, żeby agent mógł inspekcjonować twój prawdziwy schemat podczas pisania transakcji zamiast zgadywać nazwy kolumn: claude mcp add --transport stdio postgres -- npx -y @modelcontextprotocol/server-postgres "$DATABASE_URL" (ten sam pakiet w Cursor i Codex przez .mcp.json; zarchiwizowany u źródła, ale wciąż się instaluje i działa). Z nim podłączonym “decrement stock atomically” zamienia się w czytanie przez agenta faktycznej tabeli Product, potwierdzenie typu kolumny stock i napisanie pasującej transakcji — różnica przed/po to mniej rundek na poprawianie wymyślonych nazw pól. W developmencie używaj connection stringa tylko do odczytu.
Scenariusz: Twoje API przetwarza wysyłki obrazów synchronicznie, blokując odpowiedź na 30 sekund. Potrzebujesz przetwarzania w tle.
Wskazówka
Set up BullMQ for background job processing. (1) Create a job queue configuration in src/infrastructure/queue.ts with Redis connection, default job options (attempts: 3, backoff exponential), and typed job definitions using TypeScript. (2) Create job processors: processImageUpload (resize to multiple sizes, convert to WebP, upload to S3, update database record), sendEmail (render template, send via Resend, log delivery status), generateReport (query database, generate PDF, store in S3, notify user). (3) Create a queue dashboard at /admin/queues using @bull-board/express for monitoring jobs. (4) Add job scheduling: daily report generation at 2 AM using BullMQ’s repeat option. (5) Implement graceful shutdown: stop accepting new jobs, wait for active jobs to complete (max 30 seconds), then force-close. (6) Add dead letter queue handling: after 3 failures, move to DLQ and send an alert to the ops channel. Test job processing, retry behavior, and failure handling.
Oczekiwany output: Konfiguracja kolejki, 3 procesory, trasa dashboardu, zaplanowane zadania, graceful shutdown i testy.
Scenariusz: Twoja aplikacja czatu odpytuje serwer co 2 sekundy. Potrzebujesz wiadomości w czasie rzeczywistym.
Wskazówka
Implement WebSocket communication using Socket.io with the Express server. (1) Set up Socket.io with CORS configuration, JWT authentication middleware (verify token on connection, reject unauthorized), and Redis adapter for horizontal scaling across multiple server instances. (2) Create room management: users join rooms based on conversation IDs. Create joinRoom(conversationId), leaveRoom(conversationId), and sendMessage(conversationId, content) handlers. (3) Implement typing indicators: emit ‘typing’ when a user starts typing, debounce to stop after 3 seconds of inactivity. (4) Implement presence tracking: maintain an online/offline status per user in Redis, broadcast status changes to relevant rooms. (5) Message delivery acknowledgment: client acknowledges receipt, server marks as delivered, then read. Handle offline message queuing: store messages for offline users and deliver on reconnect. (6) Add reconnection handling with exponential backoff on the client side. Test message delivery, presence updates, and multi-instance broadcasting.
Oczekiwany output: Konfiguracja Socket.io, handlery pokojów, system obecności, potwierdzanie wiadomości i testy.
Scenariusz: Twoje logi produkcyjne to instrukcje console.log bez struktury, bez korelacji i bez sposobu na prześledzenie żądania między serwisami.
Wskazówka
Implement structured logging with Pino. (1) Configure Pino with JSON output in production and pretty-print in development. Set log levels per environment (debug in dev, info in production). (2) Create a request logging middleware that assigns a unique requestId (from X-Request-Id header or generated UUID) and logs: method, URL, status code, response time, user ID (if authenticated), and request body (redacted for sensitive fields like password, token, creditCard). (3) Create a logger.child({ requestId }) pattern so every log within a request includes the requestId for correlation. (4) Add sensitive field redaction: define a list of field names (password, token, secret, authorization) that are automatically replaced with ‘[REDACTED]’ in all log output. (5) Create a custom error serializer that includes stack traces in development but omits them in production. (6) Set up log shipping to stdout for container environments (picked up by Datadog/ELK). Test that request IDs propagate through nested function calls and that sensitive fields are redacted.
Oczekiwany output: Konfiguracja Pino, middleware żądań, wzorzec child loggera, reguły redakcji i testy.
Scenariusz: Twoje API jest na żywo z płacącymi klientami i musisz dostarczyć breaking changes bez psucia ich integracji.
Wskazówka
Implement API versioning with OpenAPI documentation. (1) URL-based versioning: mount v1 routes at /api/v1/ and v2 routes at /api/v2/. Create a router factory that accepts a version and returns configured routes. V1 stays frozen for backwards compatibility. (2) Create an OpenAPI 3.1 spec using swagger-jsdoc: annotate each route handler with JSDoc comments defining parameters, request body schema (reference Zod schemas), response schemas, and error responses. (3) Serve Swagger UI at /api/docs for interactive documentation. (4) Generate TypeScript types from the OpenAPI spec for client SDKs using openapi-typescript. (5) Add a deprecation middleware: when a v1 endpoint has a v2 replacement, add Deprecation and Sunset headers with the sunset date. Log deprecation warnings. (6) Create a migration guide document listing every v1-to-v2 change. Test that v1 endpoints still work unchanged and v2 endpoints serve new behavior.
Oczekiwany output: Wersjonowany router, adnotacje OpenAPI, konfiguracja Swagger UI, middleware deprecation i testy.
Scenariusz: Twój endpoint uploadu plików ładuje cały plik do pamięci, wykłada się na plikach powyżej 100 MB i akceptuje dowolny typ pliku.
Wskazówka
Implement production-grade file uploads with multer and streaming. (1) Configure multer with disk storage for temporary files, file size limit (50 MB), file type validation (accept only images and PDFs by checking both MIME type and magic bytes, not just extension). (2) Create a streaming upload to S3: pipe the file stream directly to S3 using the AWS SDK v3 multipart upload, never loading the full file into memory. (3) Image processing pipeline: for image uploads, use sharp to generate thumbnails (150x150), medium (800x600), and original size. Convert all to WebP. Upload all variants to S3 with proper Content-Type headers. (4) Return a response with URLs for each variant. Store the file metadata in the database (original name, size, mime type, S3 keys, upload date). (5) Add virus scanning using ClamAV via a ClamScan integration before processing. (6) Cleanup: delete the temporary file after processing, add a scheduled job that cleans orphaned S3 objects not referenced in the database. Test upload with valid/invalid files, oversize files, and virus-infected test files.
Oczekiwany output: Trasa uploadu, strumieniowanie do S3, przetwarzanie obrazów, skanowanie antywirusowe, zadanie czyszczące i testy.
Scenariusz: Twoja baza danych jest miażdżona przez powtarzające się identyczne zapytania. Strona listy produktów wykonuje to samo zapytanie 10 000 razy na minutę.
Wskazówka
Implement a caching layer using Redis. (1) Create a CacheService class with typed methods: get<T>(key), set<T>(key, value, ttl), delete(key), deletePattern(pattern). Handle Redis connection failures gracefully — if Redis is down, bypass cache and hit the database directly (circuit breaker pattern). (2) Create a cacheMiddleware(options) Express middleware: check cache for GET requests, return cached response if fresh, otherwise proceed to handler and cache the response. Use ETags for conditional requests. (3) Implement cache invalidation: when a product is updated, delete the product detail cache AND the listing cache. Use cache tags: tag each cache entry with resource type, invalidate by tag. (4) Add cache warming: on server start, preload the top 100 most-accessed resources. (5) Implement stale-while-revalidate: serve stale cached data immediately while fetching fresh data in the background. (6) Monitor cache hit rate and size via a /admin/cache/stats endpoint. Test cache hits, misses, invalidation, and Redis failure fallback.
Oczekiwany output: CacheService, middleware, logika inwalidacji, skrypt rozgrzewający, endpoint monitorowania i testy.
Scenariusz: Twoja aplikacja Node.js wdraża się przez SSH i ręczne npm install na serwerze. Czas na konteneryzację i automatyzację.
Wskazówka
Create a production deployment pipeline. (1) Multi-stage Dockerfile: build stage installs dependencies and compiles TypeScript, production stage copies only compiled JS and production node_modules, uses node:22-alpine (maintenance LTS; Node 24 is the current Active LTS - any maintained LTS works), runs as non-root user, adds healthcheck, uses dumb-init for signal handling. Final image under 150 MB. (2) docker-compose.yml for local development: app with hot reload (volume mount src/), PostgreSQL, Redis, Mailhog for email testing. docker-compose.prod.yml with proper resource limits. (3) GitHub Actions workflow: on PR — lint, type-check, test with PostgreSQL service container. On merge to main — build Docker image, push to GitHub Container Registry, deploy to staging with health check verification, manual approval for production deploy. (4) Database migration step: run prisma migrate deploy before starting the new container. (5) Rollback strategy: if the health check fails after deploy, revert to the previous image tag. Test the Docker build and health check endpoint.
Oczekiwany output: Dockerfile, pliki compose, workflow GitHub Actions, skrypt migracji i strategia rollbacku.
Notatka
Dla połowy CI/CD serwer GitHub MCP (@modelcontextprotocol/server-github) pozwala agentowi przeczytać twoje istniejące workflowy, ochronę gałęzi i kilka ostatnich nieudanych przebiegów, zanim napisze nowy pipeline — dzięki czemu pasuje do sekretów i wymaganych checków twojego repo, zamiast wypluwać generyczny szablon. Lżejsza alternatywa: zainstaluj jednozadaniowy skill do pisania workflowów ze skills.sh przez npx skills add <owner/repo> (CLI vercel-labs/skills; działa w Claude Code, Cursor i Codex), gdy potrzebujesz tylko jednorazowego scaffoldingu i nie chcesz trwałego połączenia. Zasada kciuka: skill do generacji jednorazowej, serwer MCP, gdy agent musi nieustannie odpytywać GitHub.
Uwaga
Częste pułapki Node.js:
Nieobsłużone odrzucenia promise: Jeśli AI zapomni owinąć asynchroniczne route handlery, nieobsłużone odrzucenia crashują proces w Node 20+. Zawsze używaj wrappera catchAsync lub express-async-errors.
Wycieki pamięci w domknięciach: Wypatruj event listenerów lub interwałów tworzonych w middleware, które nigdy nie są sprzątane. Każdy setInterval potrzebuje odpowiadającego clearInterval przy zamknięciu.
Wyczerpanie połączeń Prisma: Jeśli AI tworzy nowy PrismaClient na żądanie zamiast używać singletonu, wyczerpiesz pulę połączeń z bazą. Zawsze weryfikuj, że używa wzorca singleton.
Dostęp do zmiennych środowiskowych: Jeśli AI sięga po process.env bezpośrednio w całym kodzie, trudno to testować i łatwo przeoczyć brakujące zmienne. Preferuj zwalidowany moduł konfiguracji ładowany przy starcie.