Skip to content
Back to skills

Backend Patterns

ASecurity

Backend architecture patterns, API design, database optimization, and server-side best practices for Node.js, Express, and Next.js API routes.

  • 12 stars
  • 0 votes
  • 0 copies
  • 0 views
  • Added October 6, 2026
ai-agentstypescriptnextjsnodeexpressawsdebuggingapidatabasefrontendbackend

Works with

  • cli
  • api

Security analysis

A100/100

Pro scans all 11 files and shows the line behind each finding

Scanned October 6, 2026

npx -y skills add Nmor/the-council --skill backend-patterns --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Backend Patterns?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Backend Patterns
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/nmor-backend-patterns-the-council/badge)](https://www.skillsdirectory.com/skills/nmor-backend-patterns-the-council)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: backend-patterns
description: Backend architecture patterns, API design, database optimization, and server-side best practices for Node.js, Express, and Next.js API routes.
disable-model-invocation: true
---

# Backend Development Patterns

> **Size budget: 25 KB.** Check: wc -c. Gate: node ~/.claude/scripts/token-budget.mjs --check

Backend architecture patterns and best practices for scalable server-side applications.

> **Reuse-first** (per `~/.claude/rules-library/common/reuse-first.md`):
> Before creating a new service / repository / middleware /
> handler helper / validator / DTO, sweep the project's `lib/`,
> `services/`, `repositories/`, `middleware/`, `validators/`,
> `dto/` (or language-equivalent) directories. One source of
> truth per concept (one auth middleware, one error envelope, one
> pagination helper, one rate limiter, one DB client factory).
> Extend with a parameter — never fork.

## When to Activate

- Designing REST or GraphQL API endpoints
- Implementing repository, service, or controller layers
- Optimizing database queries (N+1, indexing, connection pooling)
- Adding caching (Redis, in-memory, HTTP cache headers)
- Setting up background jobs or async processing
- Structuring error handling and validation for APIs
- Building middleware (auth, logging, rate limiting)

## Pattern Routing Table

The detail lives in `references/`. Load the row you need; do not load the whole set.

| Topic | Covers | Reference |
| --- | --- | --- |
| API design + layering | RESTful URL shape, repository, service layer, middleware | `references/api-layering.md` |
| Database patterns | Query optimization, N+1 prevention, transactions | `references/database.md` |
| Caching strategies | Redis caching layer, cache-aside | `references/caching.md` |
| Error handling | Centralized error handler, retry with exponential backoff | `references/error-handling.md` |
| Authentication and authorization | JWT token validation, role-based access control | `references/auth.md` |
| Rate limiting | Simple in-memory rate limiter | `references/rate-limiting.md` |
| Background jobs and queues | Simple queue pattern | `references/background-jobs.md` |
| Logging and monitoring | Structured logging | `references/logging.md` |
| Fire-and-forget side effects | Canonical helper, usage, wrong-shape test, bug signatures | `references/fire-and-forget.md` |
| Content-hash file caching | SHA-256 cache key, frozen entries, service wrapper, anti-patterns | `references/content-hash-caching.md` |

**Remember**: Backend patterns enable scalable, maintainable server-side applications. Choose
patterns that fit your complexity level.

## Purpose

Server-side architecture patterns for Node.js / TypeScript / Next.js backends: handler structure,
repository / service layering, validation, error envelopes, caching, background jobs, structured
logging, and fire-and-forget side effects.

**Negative scope**: NOT REST contract design (see `~/.claude/skills/api-design/SKILL.md` — that owns
URL shape, status codes, pagination). NOT database schema / migrations (separate skill). NOT cloud
deployment patterns (`~/.claude/skills/aws-serverless-patterns/SKILL.md` covers Lambda specifics).
NOT frontend state management.

## When NOT to use

- Stateless function-as-a-service workloads where Lambda + DynamoDB single-table covers the use case
  — use `aws-serverless-patterns`
- Pure database query optimisation — use `postgres-patterns` or `dynamodb-patterns`
- GraphQL servers (their middleware / resolver model differs)
- BFF (backend-for-frontend) layers that are thin pass-through — overengineering risk
- Embedded / batch / CLI workloads with no HTTP surface

## Standards Cited

- **RFC 9110** (HTTP Semantics, Jun 2022) §15 — status code semantics for handlers
- **RFC 9457** (Problem Details, Jul 2023) — error envelope shape
- **OWASP ASVS 4.0.3 §4** (Access Control), §5 (Validation, Sanitisation, Encoding), §7 (Error
  Handling + Logging)
- **OWASP API Security Top 10 (2023)** — API1 BOLA, API4 Resource Consumption, API8 Security
  Misconfiguration
- **The Twelve-Factor App (12factor.net)** — IV (Backing Services), VIII (Concurrency), XI (Logs)
- **Node.js LTS Documentation** (current LTS) — stream + async patterns
- **Repository / Unit-of-Work pattern** — Fowler, *Patterns of Enterprise Application Architecture*
  (2002)

## Anti-Patterns

| Pattern | Why bad | Correct alternative |
| --- | --- | --- |
| Fat handler (DB call + business logic + serialisation in one function) | Untestable; violates single-responsibility; couples HTTP to domain | Handler → service → repository layering |
| DB connection per request (no pool) | Connection exhaustion under load; latency spike on every request | Singleton pool injected at app start; per-request connection acquired from pool |
| Synchronous `for` loop calling DB | N+1 query pattern; serial latency stacks | Batch fetch with `IN (…)` + Map lookup OR JOIN |
| `console.log` for production logging | No structure, no correlation IDs, no filterable severity | Structured logger (pino, winston, slog) with `request_id` + `trace_id` |
| Fire-and-forget `void store.save()` or `.catch(() => null)` | Silent failure; error never surfaces; bug found by user, not on-call | `fireAndForget(name, promise)` helper that logs with operation + cause |
| Caching without TTL + invalidation strategy | Cache becomes permanent stale state; user sees outdated data | Explicit TTL + invalidation hook on mutation |
| Middleware order matters (auth after parsing JSON of any size) | DoS via 100MB body before auth fires | Auth + body-size limit FIRST in middleware chain |
| Webhook handler that mutates state on every retry | Provider retries → double-charge / double-create | Idempotency key + dedupe table (see `~/.claude/rules-library/common/idempotency.md`) |

## Verification Checklist

- [ ] Handler delegates to service; service delegates to repository (3-layer)
- [ ] All input validated via schema (Zod / Joi / class-validator) at boundary
- [ ] Connection pool injected once at app start; never created per-request
- [ ] Structured logger with `request_id` propagated through async context
- [ ] Errors mapped to RFC 9457 envelope at boundary; no internal stack traces leaked
- [ ] No N+1 — every `forEach` over DB rows audited for batch alternative
- [ ] Fire-and-forget uses the canonical helper, never bare `void`/`.catch(() => null)`
- [ ] Cache keys carry version prefix so deploys can invalidate
- [ ] Rate limit + auth middleware fires BEFORE body parsing of unbounded size

## Cross-References

- `~/.claude/skills/api-design/SKILL.md` — REST contract design (URL, status, envelope)
- `~/.claude/rules-library/common/idempotency.md` — Idempotency-Key contract for mutating endpoints
- `~/.claude/rules-library/common/no-silent-failures.md` — fire-and-forget canonical shape
- `~/.claude/rules-library/common/error-handling-with-context.md` — wrap-with-context discipline
- `~/.claude/rules-library/common/rate-limiting.md` — middleware ordering + RateLimit-* headers
- `~/.claude/rules-library/common/no-ambient-globals.md` — connection pool injection vs module-level
  singleton
- `~/.claude/rules-library/common/reuse-first.md` — sweep before adding a new middleware /
  repository / DTO
- `~/.claude/skills/postgres-patterns/SKILL.md` — query optimisation
- `~/.claude/skills/observability-patterns/SKILL.md` — structured logging + trace propagation

## Why this skill exists

Backend handlers are where every customer-visible failure is born — and where the cost of
correctness is lowest at write time. The recurring failure modes:

- A handler that bundles DB + logic + serialisation grows to 300 lines, becomes untestable, and
  accumulates dark corners where validation is missed
- A connection pool created per-request exhausts under modest load (200 concurrent users ×
  1s/request = 200 simultaneous connections; Postgres default `max_connections=100`)
- N+1 queries hide in `await Promise.all(items.map(i => fetch(i.id)))` patterns; latency P99
  explodes as data grows
- Fire-and-forget side effects (audit logs, peer-tab broadcasts) lose their errors; on-call doesn't
  find out for hours
- Webhook handlers fire twice on every provider retry without an idempotency table → double-charges
  on Stripe, double-emails on SendGrid

Cost of the layered + structured-logger + idempotent + bounded-middleware pattern: minutes per
handler at write time. Cost of debugging the unstructured version: hours per incident.

## Learning hooks

Per `~/.claude/rules/common/continuous-learning-mandate.md`:

**Signals to watch**:

- Fire-and-forget side effect without `.catch` / structured failure log (sister
  `no-silent-failures.md` violation)
- Handler shape duplicates middleware logic that already exists (reuse-first weakening)
- Connection pool created per-request instead of injected from the application root
- DB call inside a loop where a JOIN / batch would work (N+1 pattern)
- Background job triggered synchronously when an outbox + worker would be safer
- Cache without TTL + invalidation strategy (cache becomes permanent stale state)
- Webhook handler not idempotent on retry (sister `idempotency.md` violation)
- Cross-request mutable state introduced (sister `no-ambient-globals.md` violation)
- Content-hash cache used as a write-through path without corruption-as-miss handling

**Refinement candidates**:

- New pattern row when a recurring backend shape emerges (e.g., outbox + transactional events, CQRS
  read model, materialized view refresh)
- New cross-reference when a sister rule (idempotency, observability, error-handling-with-context)
  adds a server-side gate
- Tightening of the fire-and-forget pattern when async errors slip past structured logging
- New cache-eviction template when a recurring staleness incident class recurs

Files in this skill

  • SKILL.md9.7 KB
  • references/api-layering.md3 KB
  • references/auth.md2.2 KB
  • references/background-jobs.md1.2 KB
  • references/caching.md1.4 KB
  • references/content-hash-caching.md4.3 KB
  • references/database.md2.2 KB
  • references/error-handling.md1.9 KB
  • references/fire-and-forget.md2.9 KB
  • references/logging.md1.5 KB
  • references/rate-limiting.md1.2 KB

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…