PABCD Initiative Documentation Hub pabcd_initiative codexclaw cli-jaw

dev-backend

Source: skills/dev-backend/SKILL.md

Framework-agnostic backend guidance for APIs, architecture, data access, and operations.

왜 별도 모듈인가
백엔드는 API 설계, DB 접근, 인증, 에러 처리, 캐싱, 큐 등 서로 다른 관심사가 교차하는 곳이다. 에이전트가 이 전체를 하나의 스킬로 다루면 모든 작업에 불필요한 컨텍스트가 로드된다. 그래서 이 스킬은 라우터 역할을 하며, C2 일반 CRUD는 crud-api.md 하나로, C3+ 작업에서만 api-design, architecture 등 심화 레퍼런스를 로드한다.
LLM 단독 사용 시 발생하는 문제

LLM의 학습 데이터는 특정 시점에 고정되어 있다(knowledge cutoff). 2024년에 학습한 모델이 2026년에 FastAPI를 쓸 때, deprecated된 API를 추천하거나 새 버전에서 변경된 동작을 모른 채 코드를 생성한다. 이건 LLM이 '모르는 것을 모르는' 문제다 — 자기가 아는 정보가 구식인지 판단할 수 없다. 그래서 모든 외부 의존 결정에 'search 스킬을 읽고 현재 문서를 확인하라'는 강제 경유를 넣었다. 또한 LLM은 복잡한 것을 선호하는 편향이 있다 — CRUD 하나에 GraphQL + 마이크로서비스를 제안하는 이유는 학습 데이터에서 그런 아키텍처가 더 많이 논의되기 때문이다. over-engineering guard는 이 편향을 명시적으로 차단한다.

이 스킬이 해결하는 실제 문제

2026 지식 컷오프와 외부 API 문서

에이전트의 학습 데이터에는 2024-2025년 API 문서가 포함되어 있지만, 프레임워크 버전(FastAPI 0.115+, Express 5.x, Next.js 15)과 라이브러리 API는 계속 변한다. 이 스킬은 모든 외부 의존 결정에 'search 스킬을 읽고 evidence-status 규칙을 따르라'는 경고를 포함한다. 기억에 의존하지 말고 현재 문서를 확인하라는 원칙이다.

과도한 아키텍처 설계 (over-engineering)

에이전트에게 API를 만들라고 하면 CRUD 엔드포인트 하나에 GraphQL + 마이크로서비스 + 이벤트 소싱을 제안하는 경우가 많다. Architecture Clarification(section 0)은 '작은 팀이면 모놀리스 + PostgreSQL + JWT가 가장 단순한 출발점'이라는 over-engineering 가드를 내장한다.

스택 감지 없는 맹목적 제안

이미 tsconfig.json이 있는 TypeScript 프로젝트에 Python FastAPI를 제안하거나, requirements.txt가 있는데 Node.js를 추천하는 실수. Stack Detection은 설정 파일을 먼저 읽고 자동 감지한 뒤 진행하게 한다.

Triggers: backend, API, REST, GraphQL, schema, migration, query optimization, middleware, OTel, caching, server

Key Concepts

  • Stack Detection
  • API Design (REST/GraphQL/gRPC/tRPC)
  • Architecture Clarification
  • Layered Backend Architecture
  • Error Handling & Result Pattern
  • Observability (OTel)
  • Caching Strategy

Sections Overview

SectionSummary
Stack Detection설정 파일로 프로젝트 타입을 자동 감지한다.
API DesignREST, GraphQL, gRPC, tRPC 중 적합한 API 스타일을 선택한다.
Error HandlingResult 패턴과 에러 응답 규약을 통해 일관된 에러 처리를 한다.
Database & ORM쿼리 최적화, N+1 방지, 마이그레이션 전략을 다룬다.
Observability프로덕션 서비스의 트레이싱, 로깅, 알러팅 설정.

Academic References

PaperYearRelevance
LLMs Meet Library Evolution: Evaluating Deprecated API Usage in LLM-based Code Completion
arXiv:2406.09834
20247개 LLM, 145개 API 매핑, 28,125개 프롬프트로 deprecated API 사용을 평가. 지식 컷오프 문제의 실증. (ICSE 2025)
When LLMs Lag Behind: Knowledge Conflicts from Evolving APIs in Code Generation
arXiv:2604.09515
20268개 Python 라이브러리의 270개 실제 API 업데이트에서 LLM의 오래된 파라메트릭 지식과 컨텍스트-메모리 충돌을 연구.

Official Guides

  • OpenTelemetry Documentation — 분산 트레이싱, 메트릭, 로깅의 공식 가이드. observability.md의 기반.
  • Google SRE Book — 에러 예산, toil 감축, 모니터링, 인시던트 대응의 표준 참고서.

Full Specification

Show full SKILL.md content

Dev-Backend — Production-Grade Backend Engineering

Build reliable, secure, and maintainable server-side applications.

This skill has modular references for specialized guidance — read the relevant ones before coding.

It activates by change surface whenever work primarily touches APIs, servers, services, jobs, data access, schemas, migrations, or operational backend behavior.

> C0/C1 work (small local patches): See dev §0.0 Work Classifier + §0.1 Patch Fast-Path before reading references.

Modular References

FileWhen to ReadWhat It Covers
references/core/crud-api.mdC2 ordinary CRUD/resource endpointsRoute/schema/service/query basics, five operations, error+permission mapping
references/core/api-design.mdNew/changed API style, or C3+ API work (C2 ordinary slice: crud-api.md alone suffices)REST conventions, response envelopes, HTTP status, pagination, GraphQL, gRPC, tRPC
references/core/api-lifecycle.mdAPI versioning, deprecation, migrationVersioning strategy, RFC 9745/8594 lifecycle, oasdiff CI gate
references/core/architecture.mdNew features at C3+ (C2 ordinary slice: crud-api.md alone suffices)Layered architecture, DDD, SOLID, when to split, monolith vs micro
references/core/anti-slop-backend.mdNew endpoints, classes, or modulesBanned patterns: god classes, raw SQL in services, magic numbers, etc.
references/core/observability.mdProduction deploymentsOpenTelemetry, structured logging, distributed tracing, alerting
references/core/health-checks.mdProduction/long-lived servicesLiveness, readiness, startup probes, dependency checks
references/core/process-isolation.mdCPU-bound or untrusted workworker_threads vs child_process vs separate service, communication, resource limits
references/core/caching.mdPerformance optimizationRedis-compatible (Valkey/Redis) patterns, CDN, connection pooling, cache invalidation
references/stacks/node.mdNode.js/TypeScript projectsExpress/Fastify, middleware, Zod validation, ESM, error handling
references/stacks/python.mdPython projectsFastAPI/Django, Pydantic, async patterns, testing
references/stacks/database.mdDatabase design/optimizationPostgreSQL, MongoDB, indexing, N+1, migrations, ORM comparison
references/core/ml-serving.mdML model deployment, GPU inferencevLLM/SGLang runtime selection, FastAPI+GPU patterns, dynamic batching, quantization
references/core/llm-integration.mdRAG, LLM API integration, prompt engineeringChunking, hybrid search, vector DB, structured output, LangChain/LlamaIndex 2026
references/core/mobile-api.mdMobile app API patternsBFF, push notifications, offline sync, mobile auth, API optimization

Read api-design.md + anti-slop-backend.md first, then the relevant stack file.

For C2 ordinary slices, crud-api.md alone suffices; read api-design.md/architecture.md for new API styles or C3+ work.

When backend decisions depend on current external API docs, API lifecycle

changes, LLM/RAG provider behavior, dependency freshness, or package/source

evidence, read the active search skill and follow its query-rewrite,

source-fetch, and evidence-status rules.

---

0. Stack Detection & Architecture Clarification

Auto-detect (existing projects)

File FoundProject Type
tsconfig.jsonTypeScript (Node)
package.json (no ts)JavaScript (Node)
pyproject.toml/requirements.txtPython
go.modGo
Cargo.tomlRust

If config files exist → detect silently and proceed.

Architecture Clarification (new or ambiguous projects)

When the request has unspecified technology or unclear scope, clarify before coding:

  1. Identify what's ambiguous from this list:
DimensionOptions to present
API styleREST (default) · GraphQL (BFF/mobile) · gRPC (internal microservices) · tRPC (TS monorepo)
DatabasePostgreSQL (default, ACID) · MongoDB (flexible schema) · SQLite (embedded)
Auth methodJWT + refresh (stateless) · Session-based (simple) · OAuth 2.1 (3rd party)
RealtimeNot needed (default) · WebSocket · SSE · Polling
ArchitectureMonolith (default) · Modular monolith · Microservices
  1. Recommend one with reasoning: cite project context. e.g., "Small team → monolith + PostgreSQL + JWT is the simplest starting point."
  2. Over-engineering guard: A CRUD API *probably* doesn't need GraphQL + microservices + event sourcing. Simple → complex, not the reverse.
  3. One round limit: 2-3 options → recommend → confirm → proceed.

If the user already specifies clear tech (e.g. "FastAPI로 REST API 만들어줘"), skip this entirely.

Node/framework defaults (verified 2026-07-02): production uses Active/Maintenance

LTS — Node 24 (Active LTS) for new services, Node 22 (Maintenance). Framework: Fastify

for greenfield Node APIs (schema/Pino/plugin structure); Express 5 for legacy/ecosystem

compatibility; Hono for edge/serverless/multi-runtime Web-Standards APIs. New TS

validation baseline is Zod v4 (read the migration guide before upgrading v3 projects).

Sources: references/stacks/node.md § Sources.

For new Node backend source files, prefer .ts when the repo supports TypeScript or is greenfield. Inherit dev TypeScript strict-compatibility rules.

If backend boundaries are unclear, read existing source-of-truth docs/logs first, then document routes, services, repositories, data stores, and runtime commands in the repo's existing SOT before broad implementation.

---

1. Architecture Decision

Before coding, identify the right pattern:

Team SizeDefault Starting Point
1-3 devsModular monolith
4-10 devsModular monolith or SOA
10+ devsConsider microservices

Default to monolith. Extract only when you have a proven need (different scaling, independent deployment, technology mismatch).

See references/core/architecture.md for full decision matrices.

API Protocol Decision

ProtocolChoose WhenAvoid When
RESTPublic/partner APIs, simple CRUD, caching mattersClients need flexible data shapes
GraphQLMobile/BFF client aggregation, multiple resources per requestSimple CRUD, server-to-server, file uploads
gRPCInternal microservices, high-perf binary, bidirectional streamingBrowser clients (without gRPC-Web), public APIs
tRPC (v11)TypeScript shared end-to-end: monorepo, internal toolsPolyglot environments, public APIs

Hybrid pattern (verified 2026-07-02):

Public/Partner → REST (OpenAPI 3.1+; prefer 3.2 where tooling supports it)
Mobile/Web BFF → GraphQL (client aggregation; Apollo Federation ONLY when multiple
                 independently-owned subgraphs must compose into a supergraph)
Internal services → gRPC (Protobuf contracts)
TS internal tools → tRPC v11 (zero-codegen type safety)

Deprecations: emit Deprecation (RFC 9745) and optional Sunset (RFC 8594) headers,

but client adoption is uneven — always pair with OpenAPI/changelog dates and deprecated-

endpoint traffic dashboards.

See references/core/api-design.md for protocol-specific patterns.

Long-Lived Connection Operation

Rules for SSE, WebSocket, and any connection held open beyond a single request-response cycle.

Lifecycle Rules:

ParameterDefaultRationale
Heartbeat interval15-30sDetect dead connections before TCP timeout (varies by proxy)
Reconnection backoffExponential 1s-30s with jitterPrevent thundering herd on server restart
Max connection duration1h (SSE), 24h (WebSocket)Force reconnect to rebalance and prevent memory leaks
Connections per clientCap at 6 (SSE) or 1-2 (WebSocket)Browser limits + server memory budget

Server-Side Requirements:

  • Connection registry: Track all active connections in-memory (Map by client/session ID). Required for graceful drain and debugging.
  • Graceful drain on deploy: Stop accepting new connections → send "reconnect" frame to existing → wait drain timeout → close.
  • Memory budget: Allocate max memory per connection (e.g., 2KB buffer). Monitor total; reject new connections when approaching limit.
  • Backpressure: If client stops consuming, buffer up to N messages then drop oldest or disconnect.

Pattern — "202 + Job ID" for Long Operations:

Instead of holding a connection open for a slow operation:

POST /generate → 202 { jobId: "j_abc123" }
GET /jobs/j_abc123 → { status: "processing", progress: 0.6 }
                   → { status: "complete", result: {...} }

Use SSE/WebSocket only for push notifications about job status — not for the operation itself.

Banned:

BannedFix
Unbounded connections (no cap, no registry)Connection registry + cap per client + global max
No heartbeat (rely on TCP keepalive only)Application-level heartbeat every 15-30s
Blocking event loop per connection (sync work in message handler)Offload to worker thread or queue; handler stays async
Holding connection open for >5s synchronous workReturn 202 + job ID; notify via push when done
No reconnection logic on client sideImplement exponential backoff with jitter

---

2. Layered Architecture (Default; Allow Serverless Handlers, Vertical Slices, and Small Scripts When Appropriate)

Routes → Controllers → Services → Repositories → Database
  │          │             │            │
  │          │             │            └── Data access only
  │          │             └── Business logic (validation at controller boundary — service trusts caller per dev-architecture §4)
  │          └── Parse HTTP, format response
  └── URL mapping, middleware

Rules:

  • Routes: URL patterns + middleware only. No logic.
  • Controllers: parse input, call services, format output. No business rules.
  • Services: receive/return plain data (not req/res). All logic here.
  • Repositories: abstract DB access. Services access data through repositories only.

Repository Pattern (Interface Abstraction)

Use repository interfaces so services depend on abstractions, enabling mocking and swapping implementations.

Async Task Queue Patterns

When work exceeds what an HTTP response cycle should hold open, use a queue.

Decision: Queue vs Direct:

ConditionUse QueueUse Direct
Execution time >5sYesNo
Must be retryable on failureYesNo
Fire-and-forget (caller doesn't wait)YesNo
<1s, idempotent, caller needs immediate resultNoYes
Real-time user-facing validationNoYes

Pattern — Accept, Queue, Notify:

1. Client  → POST /tasks       → Server validates, enqueues
2. Server  → 202 { jobId }     → Client receives immediately
3. Worker  → picks from queue  → executes task
4. Client  → GET /tasks/{id}   → polls status (or receives webhook/SSE push)
5. Worker  → completes         → writes result, triggers notification

Queue Selection Guide:

QueueWhenNotes
BullMQ (Redis-compatible)Node.js, need retries + priorities + rate limitingMost mature Node queue; needs Redis/Valkey
Celery (Redis/RabbitMQ)Python, distributed workers, periodic tasksDe facto Python standard
pg-boss (PostgreSQL)Node.js, Postgres is the durable system of record, moderate scaleNo extra infra; SKIP_LOCKED-based
Simple DB queue (polling)Small scale (<100 jobs/min), any languagestatus column + SELECT FOR UPDATE SKIP LOCKED
SQS / Cloud TasksServerless, managed, very high scaleNo infra to manage; at-least-once delivery
TemporalDurable multi-step workflows: sagas, human-in-loop, long-running AI/business processesWorkflow engine, NOT a default queue replacement

Required Safeguards:

SafeguardRule Idempotency keyEvery enqueue call must include a unique idempotency key; dedup on insert Dead letter queue (DLQ)Failed 3x (configurable) → move to DLQ → alert → manual review
Max retriesSet explicit limit (default: 3); exponential backoff between attempts
Timeout per jobEvery job has a max execution time; kill and retry on exceed
Visibility timeoutLock duration > expected execution time; prevent duplicate processing
ObservabilityEmit metrics: queue depth, processing time p95, DLQ size, failure rate

Banned:

BannedFix
Synchronous long operation blocking HTTP response (>5s)Enqueue + return 202 + job ID
Queue without DLQAlways configure DLQ; alert on DLQ depth > 0
Infinite retries (no max)Set maxRetries=3 with exponential backoff
No idempotency (duplicate jobs on retry)Idempotency key on every enqueue; dedup in worker
No timeout on job executionSet per-job timeout; kill + mark failed on exceed
Polling without backoff (tight loop)Poll with interval (1-5s) or use blocking pop / push notification

---

3. Error Handling

TypeHTTPLog Level Validation400warn
Authentication401warn
Authorization403warn
Not found404info
Conflict409warn
Rate limit429info
Internal error500error + stack

Use a centralized AppError class (DEFAULT — when the repo already has an error convention, follow it instead). Distinguish operational vs programmer errors.

Error Taxonomy (AppError Hierarchy)

Create an AppError base class with statusCode, code, and isOperational properties. Extend for each error type (ValidationError, NotFoundError, etc.).

Result Pattern (conditional)

Consider the Result/Either pattern (e.g. neverthrow) for recoverable domain errors where explicit error handling improves clarity — adopt it only when the project scope justifies it and the repo doesn't already settle error style (HEURISTIC, not a universal requirement).

LibraryWhen to Use
neverthrowDefault choice — small explicit Result<T, E> for recoverable domain errors
EffectOnly when the app benefits from a full effect runtime: typed errors, retries, resources, concurrency, tracing, service composition

Rule: Use Result where recoverable/domain errors are first-class. Reserve try/catch for error boundaries (middleware, top-level handlers) only.

---

4. Middleware Execution Order

Apply in this sequence (order matters):

  1. Request ID generation
  2. Request logging
  3. Security headers (CORS, CSP, HSTS)
  4. Rate limiting
  5. Authentication
  6. Authorization
  7. Body parsing
  8. Input validation (schema)
  9. Route handler
  10. Error handler
  11. Response logging

---

5. API Response Contract

API endpoints should use a stable response envelope (DEFAULT) unless the protocol (GraphQL, gRPC, SSE) defines its own or the repo already has a different established contract — follow the existing contract first. Envelope, OTel, health checks, and deployment-readiness checks are production-surface concerns (dev §0.4 shared definition), conditional by project scope, not universal blockers.

Rules:

  • success boolean at top level — never infer from HTTP status alone
  • error.code is machine-readable (UPPER_SNAKE), error.message is human-readable
  • meta.requestId on every response — enables cross-service tracing
  • Pagination uses cursor-based (after/before) for large datasets, offset-based (page/pageSize) for admin UIs
  • Nullability: prefer consistent key presence; omit when sparse payloads are intentional
  • Timestamps: ISO 8601 UTC (2024-01-15T09:30:00Z), never Unix epoch in JSON
  • Money: integer cents + currency code, never floating point

See references/core/api-design.md for protocol-specific patterns (REST, GraphQL, gRPC, tRPC).

---

6. Caching Strategy

Decision rules:

  • Say Redis-compatible, not Redis-only (verified 2026-07-02): prefer Valkey

(Linux Foundation, BSD) for permissive OSS/self-hosted defaults; choose Redis when

managed-service, module, or license posture justifies it (Redis relicensed 2024;

Redis 8 added AGPLv3).

  • Cache only after correctness is proven on the uncached path.
  • Prefer cache-aside by default; use write-through only when strong consistency matters.
  • Every key has a namespace, version, stable identifier, TTL, and invalidation trigger.
  • Never cache error responses or personalized CDN responses; protect cached PII with encryption and access controls.
  • Add stampede protection for hot keys and monitor hit rate, pool exhaustion, and stale-read incidents.

See references/core/caching.md for TTL guidance, Redis-compatible cache patterns, CDN rules, invalidation triggers, connection pooling, and code examples.

---

7. Observability (OpenTelemetry)

Decision rules:

  • Production services emit traces, metrics, and structured JSON logs with requestId, traceId, and spanId.
  • OTel maturity (verified 2026-07-02): traces and metrics are Stable in JS/Python;

logs are still Development — the baseline is trace/span-correlated structured

logs + OTel traces/metrics; adopt OTel Logs export only where that maturity is acceptable.

  • Start with OTel auto-instrumentation, then add custom spans only for business-critical or non-instrumented work.
  • Never log PII, secrets, full request/response bodies, or noisy stack traces outside error boundaries.
  • Page only on customer-impacting signals tied to SLOs; use warning alerts for capacity trends.

See references/core/observability.md for OTel setup, structured logging conventions, trace propagation, dashboards, RUM correlation, and alerting guidance.

---

8. Skeleton Project Evaluation

When starting from a template or boilerplate, verify before building on top:

CheckWhat to Verify
DependenciesUp-to-date? CVEs? Unnecessary packages?
Architecture fitDoes the template's structure match your actual needs?
Auth/securityIs the auth pattern appropriate for your use case?
DatabaseIs the ORM/query builder suitable for your data model?
Dead codeRemove unused example routes, models, and middleware
Config managementEnvironment-based config, no hardcoded values

Treat templates as starting points, not gospel. Strip to essentials, then add what you need.

---

9. API Performance Targets (HEURISTIC defaults, not universal SLOs)

These are aggressive healthy-service starting budgets. Each product MUST define its own

SLOs from user journeys and alert on error-budget burn, not raw percentile thresholds

alone (Google SRE SLO practice; see observability.md Sources).

MetricDefault budgetEscalation
p50 response time (reads)≤ 50msProfile with tracing
p95 response time (reads)≤ 200ms, alert at >500ms (see observability.md)Optimization target
p95 response time (writes)≤ 500msAcceptable for complex writes
p99 response time≤ 1000msInvestigate outliers
Error rate< 0.1% target, alert at >1% (see observability.md)Optimization target
  • Measure at the handler level, not including network
  • Use Server-Timing header to expose backend timing to frontend
  • Log slow queries (> 100ms) with EXPLAIN output
  • Connection pool (long-running servers): min = CPU cores, max = CPU cores × 4; for serverless/Lambda use min = 0–2

API responses that drive UI must include descriptive error messages (not just codes) for screen reader announcement, pagination metadata (total count) for assistive technology, and Content-Language header matching response body language.

10. SEO Support Endpoints

When the app serves web pages (SSR/SSG):

  • GET /sitemap.xml — dynamic sitemap generation with <lastmod>
  • GET /robots.txt — configurable per-environment (disallow staging/preview)
  • Structured data: provide JSON-LD data in API responses when frontend needs it
  • Redirect chains: max 1 hop (301 for permanent, 308 for POST-preserving)

11. Deployment Patterns

Deployment strategy (blue-green, canary, rollback, feature flags) is owned by

dev-devops. This skill owns the backend contract that enables safe deploys:

  • Database migrations: separate from code deploy, backward-compatible (expand-then-contract).
  • Migrations must have a rollback path (down migration or backward-compat contract).
  • Feature flags: backend provides the flag-read API; rollout strategy is dev-devops.
  • Health endpoints (/health, /ready) gate traffic cuts — see §12 and references/core/health-checks.md.

---

12. Pre-Flight Checklist

Before delivering:

  • [ ] Consistent response envelope on every endpoint
  • [ ] Input validation with schema (Zod, Pydantic, etc.)
  • [ ] Authentication middleware on protected routes
  • [ ] Rate limiting on public endpoints
  • [ ] Structured JSON logging with requestId and traceId
  • [ ] Error handler returns proper HTTP codes via AppError hierarchy
  • [ ] No raw SQL in service layer
  • [ ] No hardcoded secrets
  • [ ] Migrations have a rollback path (down migration or backward-compat contract)
  • [ ] Observability: traces and structured logs wired (see references/core/observability.md)
  • [ ] Health endpoints: /health (liveness) and /ready (readiness) — see references/core/health-checks.md
  • [ ] API performance: p95 reads ≤ 200ms, slow queries logged with EXPLAIN (§9)
  • [ ] SEO endpoints: sitemap.xml + robots.txt if serving web pages (§10)
  • [ ] Security review: delegate to dev-security/SKILL.md for production readiness
  • [ ] Stack-specific rules followed (see references/stacks/)