backend-dev
Skill2 starsChanged 4 months agoMITView on GitHub
Production-grade backend development guidance — language and framework agnostic. Use when the user asks to build an API, design a backend service, create a database schema, implement authentication, write business logic, structure a backend project, or produce server-side code of any kind.
- Reads credentials
4 other projects use a version of this.
Adopted by
Most recently taken up by
- matos-ed/skillstheir own version, first seen Oct 11, 2026
- marmelab/atomic-crmtheir own version, first seen Oct 8, 2026
- Douglasst102/AgentSkillstheir own version, first seen Sep 28, 2026
- aico-platform/guardrails-demotheir own version, first seen Jul 4, 2026
Other versions4 projects use a version of this.
Word for word · 0
None found.
Edited · 0
None found.
Wrote their own version · 4
- marmelab/atomic-crm★ 1.4ksame name
- Douglasst102/AgentSkills★ 4same name
- matos-ed/skills★ 1same name
- aico-platform/guardrails-demo★ 0same name
How matches are found. Word for word: the exact same text. Edited: shares passages with this file (“99% same” means 99% of its five-word phrases also appear here; 10% or more counts). Their own version: similar meaning, or, weakest, the same name. We can’t tell which project had it first. Projects are counted among the 200 most-starred candidates, and mentions are links to the repository we found, up to 50 per site, so both counts are a floor.
In this repository48 other files it gives its agents.
- agent-memorySkill
- ai-engineerSkill
- api-designSkill
- autoplanSkill
- benchmarkSkill
- brand-guidelinesSkill
- code-reviewerSkill
- commit-messageSkill
- database-architectSkill
- data-engineerSkill
- debuggerSkill
- design-explorerSkill
- devex-engineerSkill
- devops-platformSkill
- doc-coauthoringSkill
- forward-deployment-engineerSkill
- frontend-designSkill
- internal-commsSkill
- java-developmentSkill
- land-and-deploySkill
- mcp-builderSkill
- office-hoursSkill
- pdfSkill
- performance-optimizerSkill
- plan-ceo-reviewSkill
- plan-design-reviewSkill
- plan-eng-reviewSkill
- pptxSkill
- product-engineerSkill
- prompt-engineerSkill
- python-developmentSkill
- qa-engineerSkill
- react-developmentSkill
- release-engineerSkill
- research-agentSkill
- retro-engineerSkill
- safety-guardrailsSkill
- security-engineerSkill
- skill-creatorSkill
- spec-authorSkill
- sre-canarySkill
- system-designSkill
- technical-writerSkill
- test-writerSkill
- theme-factorySkill
- typescript-developmentSkill
- webapp-testingSkill
- xlsxSkill
The file
Show its rules and text
We split this skill into the rules it gives an agent
39 rules. About 0 are common, 35 are distinctive, and 4 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈35
Distinctive · estimate
This author's own choices. Worth a look.
4
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Distinctive: line 14
Before any code, establish:
- Distinctive: line 27
Before writing any implementation code, work through these steps in order:
- Distinctive: line 36
Do not skip to implementation.
- Distinctive: line 42
Always generate a clean, domain-driven folder structure.
- Very specific: line 73
Never cross layers — a repository never calls a service, a model never imports middleware.
- Distinctive: line 79
Every API must be designed contract-first.
- Distinctive: line 83
Use correct HTTP methods: GET (read), POST (create), PUT (replace), PATCH (partial update), DELETE (remove)
- Distinctive: line 93
Use this as the starting point unless the project has an established convention — consistency within a codebase matters more than the …
- Distinctive: line 95
Never expose stack traces or database errors in responses
- Distinctive: line 96
Every endpoint must have an OpenAPI/schema definition — auto-generate where possible
- Distinctive: line 109
Every piece of generated backend code MUST follow these rules — no exceptions:
- Distinctive: line 112
All function signatures must have explicit input and output types
- Distinctive: line 114
No implicit any / untyped parameters — if a type is unknown, make it explicit and handle it
- Distinctive: line 117
Never swallow errors silently — every caught error must be logged or re-thrown
- Distinctive: line 118
Use custom error classes with error codes, not raw strings
- Distinctive: line 120
All async operations must have error handling — no unhandled promise rejections, no unchecked results
- Distinctive: line 126
Never trust external data: third-party APIs, user uploads, webhook payloads
- Very specific: line 131
No abbreviations unless universally understood (id, url, http)
- Distinctive: line 136
No magic numbers or magic strings anywhere in business logic
- Distinctive: line 137
All configuration comes from environment variables — never hardcoded
- Distinctive: line 139
Every required environment variable must be validated on startup — crash early with a clear message rather than failing mysteriously later
- Distinctive: line 167
Avoid over-engineering: Do not introduce abstractions speculatively.
- Distinctive: line 174
If none of these apply, use the concrete type directly.
- Distinctive: line 180
Every call that leaves the process boundary is a call that can fail, hang, or return inconsistent results.
- Distinctive: line 192
Use short-lived access tokens + refresh token rotation as the default auth pattern
- Very specific: line 196
Verify resource ownership on every request — a user fetching /orders/123 must own order 123
- Distinctive: line 199
Never log passwords, tokens, secrets, or PII in any log line — ever
- Distinctive: line 205
Every service function, utility, and repository method gets a unit test.
- Distinctive: line 220
Test behaviour, not implementation — test what a function does, not how it does it
- Distinctive: line 223
Use factories/builders for test data — never hardcode raw objects scattered across test files
- Distinctive: line 224
Test the sad path as rigorously as the happy path: invalid input, missing data, dependency failures, edge cases
- Distinctive: line 225
Every test must be independent — no shared mutable state between tests, no order dependency
- Distinctive: line 242
Test the full stack from HTTP request to DB response for critical paths
- Distinctive: line 244
Test unhappy paths at the integration level too: DB constraint violations, duplicate keys, connection failures
- Distinctive: line 250
Before marking any backend feature complete, verify:
- Distinctive: line 267
Every backend service must be observable from day one:
- Very specific: line 280
Every environment variable required at startup must be listed in .env.example with a description comment
- Distinctive: line 283
Never use production credentials in development or test environments
- Distinctive: line 290
Every backend project ships with:
≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
Backend Development
Approach every backend task as a senior engineer who has been burned by shortcuts in production. You are not here to make something that works once — you are here to make something that works at 3am on a Saturday when no one is watching. Every decision defaults to correctness, observability, and maintainability over cleverness or speed.
Step 0: Ground the Work Before Writing a Line
Before any code, establish:
- What is this service's single responsibility? Name it in one sentence. If you can't, the scope needs splitting.
- What are the data boundaries? What goes in, what comes out, what persists.
- What can fail? External calls, DB writes, auth checks — enumerate failure points before coding happy paths.
- What does done look like? Define the contract: endpoint, schema, or interface the caller expects.
State these four things explicitly to the user if the brief is ambiguous. Never silently assume.
Execution Workflow
Before writing any implementation code, work through these steps in order:
- Understand the contract — name the endpoint or function signature, its inputs, outputs, and error cases
- Map the layers — decide what belongs in
api/,services/,repositories/, and whether any new models or errors are needed - Identify external dependencies — list every DB call, external API, queue, or file system access the feature requires
- Enumerate failure modes — for each dependency, ask: what happens if it is slow, returns nothing, or fails entirely?
- Define the tests first — name the unit test cases before writing the implementation; if you cannot name them, the design is unclear
- Then implement — follow the layer rules, apply the coding standards, handle every failure mode you named
Do not skip to implementation. A feature built on a vague contract costs more to fix than the time spent grounding it.
Folder Structure
Always generate a clean, domain-driven folder structure. The structure must communicate the architecture at a glance. Follow this pattern regardless of language or framework:
project-root/
├── src/
│ ├── api/ # Route handlers / controllers — thin layer only
│ │ └── v1/ # Versioned from day one
│ ├── services/ # Business logic — no framework code here
│ ├── repositories/ # All data access — DB queries live here only
│ ├── models/ # Domain entities and data types
│ ├── middleware/ # Auth, logging, rate limiting, error handling
│ ├── config/ # Environment config, constants, feature flags
│ ├── utils/ # Pure helper functions — stateless, no side effects
│ └── errors/ # Custom error classes and error codes
├── tests/
│ ├── unit/ # One test file per source file
│ ├── integration/ # Tests that hit real DB / external services
│ └── fixtures/ # Shared test data and factories
├── migrations/ # Database migration files — versioned, never edited
├── scripts/ # One-off ops scripts, seeding, utilities
├── docs/ # API docs, ADRs, architecture diagrams
├── .env.example # Template — never commit .env
├── Dockerfile # Multi-stage, non-root user
├── docker-compose.yml # Local dev environment
└── README.md # Setup, run, test — nothing elseRules:
api/handlers must be thin — validate input, call a service, return a response. No business logic.services/must be framework-agnostic — they should be callable from a test without spinning up a server.repositories/are the only place that know about the database. No raw queries elsewhere.- Never cross layers — a
repositorynever calls aservice, amodelnever importsmiddleware.
API Design
Every API must be designed contract-first. Define the interface before implementing it.
Mandatory conventions:
- Version from day one:
/api/v1/resource - Use correct HTTP methods: GET (read), POST (create), PUT (replace), PATCH (partial update), DELETE (remove)
- Return consistent HTTP status codes — never return 200 for an error
- For new REST APIs, default to a consistent response envelope:
Use this as the starting point unless the project has an established convention — consistency within a codebase matters more than the specific shape.// Success { "data": { ... }, "meta": { ... } } // Error { "error": { "code": "RESOURCE_NOT_FOUND", "message": "...", "details": [...] } } - Paginate all list endpoints — cursor-based preferred for large datasets, offset for simple cases
- Never expose stack traces or database errors in responses
- Every endpoint must have an OpenAPI/schema definition — auto-generate where possible
Request handling checklist for every endpoint:
- Validate and sanitize all input at the boundary before it touches any logic
- Authenticate — verify identity
- Authorize — verify permission for this specific resource
- Execute business logic via service layer
- Return typed, documented response
Code Quality Standards
Every piece of generated backend code MUST follow these rules — no exceptions:
Types & Contracts
- All function signatures must have explicit input and output types
- Define data contracts (schemas/interfaces/structs) for every external boundary: API input, API output, DB row, event payload
- No implicit any / untyped parameters — if a type is unknown, make it explicit and handle it
Error Handling
- Never swallow errors silently — every caught error must be logged or re-thrown
- Use custom error classes with error codes, not raw strings
- Distinguish operational errors (invalid input, not found) from programmer errors (null dereference, wrong type)
- All async operations must have error handling — no unhandled promise rejections, no unchecked results
- Errors bubble up to a single top-level error handler that formats and logs them consistently
Defensive Programming
- Validate all external input: API requests, environment variables, config values, message queue payloads
- Fail fast — check preconditions at the top of a function, not buried in the middle
- Never trust external data: third-party APIs, user uploads, webhook payloads
Naming & Clarity
- Functions named as verbs:
getUserById,sendWelcomeEmail,calculateTax - Variables named as nouns:
userId,orderTotal,connectionPool - No abbreviations unless universally understood (
id,url,http) - One concept per function — if a function does two things, split it
- Comments explain why, not what — if the code needs a comment to explain what it does, rewrite the code
Constants & Configuration
- No magic numbers or magic strings anywhere in business logic
- All configuration comes from environment variables — never hardcoded
- Group related constants into named objects/enums
- Every required environment variable must be validated on startup — crash early with a clear message rather than failing mysteriously later
Database Rules
- Migrations only — never mutate a schema manually; every change is a versioned, reversible migration file
- Indexes driven by query patterns — add indexes for the queries you actually run; over-indexing slows writes; document the query that justifies each index in the migration comment
- Transactions when atomicity is required — wrap multi-step writes that must succeed or fail together in a transaction; not every multi-row operation needs one — use judgement
- Soft deletes when the business requires it — use
deleted_attimestamps when audit history, undo, or compliance matters; hard deletes are correct when data has no retention requirement - Timestamps everywhere — every table gets
created_atandupdated_atby default - Parameterized queries only — never interpolate user input into a query string
- Connection pooling — configure min/max pool size; never open unbounded connections
- Read replicas when scale requires it — design repositories so read/write routing can be introduced later without touching service code; do not add the complexity before you need it
SOLID and Dependency Design
Apply SOLID principles as engineering judgement, not as a checklist. The goal is code that is easy to change, easy to test, and honest about its dependencies.
- Single Responsibility — a module has one reason to change. A service that sends emails and processes payments will be painful to test and painful to change. Split them.
- Open/Closed — extend behaviour by adding code, not by editing existing logic. New payment providers, new notification channels, new export formats should slot in without touching working code.
- Liskov Substitution — any implementation of an interface must honour the contract of that interface. A mock in tests must behave like the real thing in the ways the caller depends on.
- Interface Segregation — callers should not depend on methods they do not use. A
UserRepositoryinterface used by the auth service should not expose bulk-export methods only the admin service needs. - Dependency Inversion — high-level modules (services) depend on abstractions, not on concrete implementations (a specific DB client, a specific email provider). Wire concrete implementations at the composition root.
- Composition Root — all dependency wiring happens in one place at startup. Services do not construct their own dependencies. This makes the dependency graph readable and testable.
Avoid over-engineering. Do not introduce abstractions speculatively. Create an abstraction only when one of these is true:
- Multiple implementations exist now or are planned imminently
- The dependency crosses an external boundary (DB, HTTP, file system, queue)
- The dependency is nondeterministic (time, random, environment)
- It must be replaced in tests with a controlled substitute
- It represents a stable domain capability that multiple consumers will share
If none of these apply, use the concrete type directly.
Reliability and External Dependencies
Every call that leaves the process boundary is a call that can fail, hang, or return inconsistent results. Design for this explicitly.
- Timeouts — set an explicit timeout on every outbound call; never rely on the remote end to close the connection
- Retries with backoff — retry transient failures (network errors, 429s, 503s) with exponential backoff and jitter; do not retry non-idempotent operations unless the operation is safe to repeat
- Idempotency — design write operations to be safely retryable; use idempotency keys for payment and order operations; ensure that processing a message twice produces the same outcome as processing it once
- Message queues — use queues to decouple producers from consumers and to absorb load spikes; consumers must be idempotent; dead-letter queues are mandatory for any queue used in production
- Transactional outbox — when a DB write and a message publish must happen together, write the event to an outbox table in the same transaction as the business data, then publish from the outbox asynchronously; this prevents silent message loss on process crash
Authentication & Authorization
- Use short-lived access tokens + refresh token rotation as the default auth pattern
- Hash all passwords with a strong adaptive algorithm (bcrypt cost ≥ 12, or argon2id)
- Store tokens in httpOnly cookies for browser clients; never in localStorage
- Implement RBAC — every protected route checks both authentication (who are you?) and authorization (can you do this to this resource?)
- Verify resource ownership on every request — a user fetching
/orders/123must own order 123 - Implement account lockout after repeated failed attempts
- Rotate secrets on a schedule; invalidate all sessions on password change
- Never log passwords, tokens, secrets, or PII in any log line — ever
Unit Testing
Every service function, utility, and repository method gets a unit test. No exceptions.
Structure of every test file:
describe('<ModuleName>', () => {
describe('<methodName>', () => {
it('returns X when given valid input Y')
it('throws ErrorCode.X when input is missing')
it('calls dependency Z exactly once with correct args')
it('does not call dependency Z when condition is false')
})
})Rules:
- Test behaviour, not implementation — test what a function does, not how it does it
- One assertion concept per test — a test that checks three things is three tests
- Mock all external dependencies (DB, HTTP, file system, clock) in unit tests — a unit test never hits the network or disk
- Use factories/builders for test data — never hardcode raw objects scattered across test files
- Test the sad path as rigorously as the happy path: invalid input, missing data, dependency failures, edge cases
- Every test must be independent — no shared mutable state between tests, no order dependency
- Aim for 80%+ line coverage on
services/andutils/; 100% on critical auth and payment paths
For every public function, generate tests that cover:
- Happy path with valid input
- Missing required input
- Invalid type / format input
- Boundary values (empty string, zero, max int, null)
- Dependency throws an error
- Dependency returns empty / null
- Concurrent / race condition if applicable
Integration Testing
- Integration tests live in
tests/integration/and run against a real database (use containers or an in-memory equivalent) - Test the full stack from HTTP request to DB response for critical paths
- Each integration test must clean up its own data — use transactions that rollback, or explicit teardown
- Test unhappy paths at the integration level too: DB constraint violations, duplicate keys, connection failures
Security Checklist
Before marking any backend feature complete, verify:
- All inputs validated and sanitized at the API boundary
- SQL/NoSQL injection impossible (parameterized queries / ORM)
- Authentication required on all non-public endpoints
- Authorization checks resource ownership, not just role
- Sensitive data (passwords, tokens, keys) never logged or returned in responses
- Rate limiting applied to auth endpoints and expensive operations
- CORS configured to a whitelist, not
*for credentialed requests - Security headers set on all responses
- Dependencies audited for known vulnerabilities
- Secrets loaded from environment, not source code
Observability
Every backend service must be observable from day one:
- Structured logging — every log line is a machine-readable JSON object with:
timestamp,level,message,correlationId,service, and relevant context fields - Correlation IDs — generate a unique ID per request at the entry point; thread it through every log line, every downstream call
- Log levels used correctly:
DEBUGfor dev-only detail,INFOfor significant state changes,WARNfor recoverable issues,ERRORfor failures that need attention - Health endpoints — every service exposes
/health(liveness) and/ready(readiness) with no auth required - Key metrics to instrument: request count, error rate, latency (p50/p95/p99), DB query time, external call duration
- Never log PII — mask emails, phone numbers, card numbers before they reach any log line
Environment & Configuration
- Every environment variable required at startup must be listed in
.env.examplewith a description comment - Validate all required env vars on startup — if one is missing, crash immediately with a clear error naming the missing variable
- Separate config by environment:
development,test,staging,production - Never use production credentials in development or test environments
- Feature flags for anything that needs to be toggled without a deploy
Docker & Local Dev
Every backend project ships with:
Dockerfile (multi-stage):
- Stage 1: install dependencies
- Stage 2: build / compile
- Stage 3: minimal runtime image, non-root user, only production artifacts
docker-compose.yml:
- App service
- Database service with a named volume
- Cache service (if applicable)
- Any other backing services (queue, search, etc.)
- Health checks on all services
- Environment variables loaded from
.env
Definition of Done
A backend feature is not done until:
- Folder structure follows the project convention
- All inputs validated at the API boundary
- Business logic isolated in the service layer
- Data access isolated in the repository layer
- All error cases handled and logged
- Unit tests written for all service and utility functions
- Integration test written for the critical path
- Security checklist passed
- OpenAPI / schema definition updated
.env.exampleupdated if new env vars added- README updated if setup steps changed
- No secrets, no magic numbers, no TODO comments left in committed code
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

