AgentStack
SKILL verified MIT Self-run

Backend Engineering

skill-santim025-agent-skills-backend-engineering · by santim025

Build, review and harden backend services - REST and GraphQL APIs, database schema and query design, authentication and authorization, caching, background jobs, observability and performance. Use when designing or implementing API endpoints, modeling or optimizing database queries (Postgres, MySQL, MongoDB), adding auth (JWT, OAuth, sessions), writing business logic, debugging slow backends, or r…

No reviews yet
0 installs
7 views
0.0% view→install

Install

$ agentstack add skill-santim025-agent-skills-backend-engineering

✓ scanned · ✓ verified — works with Claude Code, Cursor, and more.

Security review

✓ Passed

No issues found. Passed automated security review. · v0.1.0 How review works →

  • Prompt-injection patterns
  • Secret / credential exfiltration
  • Dangerous shell & filesystem operations
  • Untrusted network calls
  • Known-malicious package signatures

What it can access

  • Network access No
  • Filesystem access No
  • Shell / process execution No
  • Environment & secrets No
  • Dynamic code execution No

From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.

Are you the author of Backend Engineering? Claim this listing to set pricing, connect Stripe payouts, and keep 70% of every sale.
Sign up to claim

About

Backend Engineering

Senior-level workflow for designing, building and reviewing backend systems. Language- and framework-agnostic: detect the project's stack first, then apply the idiomatic patterns for it.

These standards are mandatory, not aspirational. Producing working code that skips tests, duplicates contracts, or omits contract docs is incomplete work — treat it as a failed task, not a shortcut.

When to use

  • Designing or implementing API endpoints (REST or GraphQL).
  • Modeling data or optimizing slow database queries.
  • Adding or reviewing authentication / authorization.
  • Implementing business logic, background jobs, or integrations.
  • Debugging latency, memory, or reliability problems on the server.

Greenfield vs existing codebase (read first)

Decide which mode you are in before applying anything below:

  • New project (greenfield): you set the architecture. Apply every standard here from the start (layering, shared contracts module, test project, one type per file).
  • Existing project (adding a controller / feature / fix): conform to the project's existing conventions — its folder structure, layering, naming, error-handling approach, and test setup. The standards below apply to the code you add or change, expressed in the project's established style. Specifically:
  • Match the surrounding patterns; do NOT restructure the repo or migrate it to a different architecture because you'd prefer it.
  • Reuse the existing test harness/framework and mocking style; only create a test project if there genuinely isn't one.
  • Put new contracts/types where the project already keeps equivalents (only introduce a shared module if the project lacks one AND duplication is otherwise unavoidable).
  • Apply the coverage gate to the new/changed code, not as a mandate to raise the whole legacy codebase.
  • If you spot pre-existing problems (bugs, missing tests, duplication), report them as separate recommendations — do not silently refactor beyond the requested scope. Ask before large changes.

When in doubt about a convention, mirror the nearest existing example in the codebase.

Definition of Done (non-negotiable gate)

Do NOT tell the user a backend task is finished until every item passes. State this checklist explicitly in your final summary and mark each item. In an existing project, each item is scoped to the code you added or changed and is satisfied using the project's existing conventions (see the section above) — not by restructuring the repo.

  • [ ] Tests exist and pass. Every new/changed unit of logic has unit tests; cross-boundary behavior (HTTP, DB, queue) has an integration test. If the project has no test project/harness, you create one as part of the task — never skip it.
  • [ ] Error & edge paths are tested, including the not-found / invalid-input / upstream-failure cases — not just the happy path.
  • [ ] Coverage ≥ 90% (line AND branch). Run the coverage tool and report the numbers. The threshold applies to EVERY production layer — including infrastructure adapters and error-handling middleware — not just the easy domain/application layers. If any layer is below 90%, add the missing tests before declaring done; do not average a weak layer away behind strong ones.
  • [ ] Every layer is actually exercised. Infrastructure (HTTP clients, DB repositories) is tested by mocking the transport (e.g. HttpMessageHandler / a fake DB), NOT skipped because it "just calls an external API". Middleware, filters, and exception handlers have tests that hit their branches (success, handled error, unhandled error).
  • [ ] No duplicated contracts. Shared DTOs/models live in ONE place (a shared module/package referenced by all consumers). Never copy a model into two projects.
  • [ ] One type per file, named after the type, in the right layer/folder. No "all models in one file".
  • [ ] Contract documentation present. Public interfaces, service methods, and endpoints have doc comments (signature, params, return, errors) and the framework's API annotations (e.g. OpenAPI/Swagger ProducesResponseType, typed responses).
  • [ ] Errors are explicit and mapped to correct status codes via a single error-handling strategy (global handler/middleware), not ad-hoc per endpoint, and never leaking stack traces.
  • [ ] Config is externalized (no hardcoded URLs, secrets, timeouts, CORS origins, TTLs in code).
  • [ ] Self-review done. Run the "Anti-patterns" list against your own diff and fix anything it flags before declaring done.

If you cannot complete an item (e.g. user explicitly declined tests), say so plainly and record it as a known gap.

Engineering standards (apply to every task)

  • Languages. Stack-agnostic: detect the project's language and toolchain, then apply idiomatic conventions for it — TypeScript/JavaScript, Python, Go, Java, C#, Rust, Kotlin, Ruby, PHP, Swift, C/C++ and others (idiomatic naming, layout, test framework, formatter/linter).
  • Clean code. Intention-revealing names; small single-responsibility functions; DRY; apply SOLID where it fits; guard clauses over deep nesting; no dead code.
  • TDD & tests (enforced). Default to red-green-refactor: write the failing test first, then the code to pass it. No feature is "done" without tests — see the Definition of Done. Tests follow Arrange-Act-Assert, cover the happy path plus edge/error cases (not-found, invalid input, upstream failure), and are deterministic and isolated (mock external HTTP/DB). Add integration tests for behavior that crosses boundaries (DB, HTTP, queues).
  • Coverage (enforced ≥ 90%). Measure line and branch coverage with the stack's tool (coverlet/dotnet test --collect, c8/vitest --coverage, pytest --cov, go test -cover, JaCoCo...). Hold ≥ 90% per layer, not just overall. Branch coverage matters most where bugs hide: error handlers, if/else, null checks, switch arms. Chase meaningful coverage (assert behavior), never write empty tests just to move the number.
  • Code documentation. Document public APIs and contracts (signature, params, return, errors) and any non-obvious intent or trade-off. Do NOT write comments that narrate what the code already says.
  • Hygiene. No noise comments. No generic or decorative emojis in code, commits, or docs unless the user explicitly asks. Match the existing code style. Reply in the user's language.

Workflow

  1. Understand the contract first. Before writing code, pin down the input/output shape, error cases, auth requirements, and idempotency expectations of the endpoint or function.
  2. Set up the test harness. Ensure a test project/suite exists for the layer you're touching; create it if missing. This is part of the task, not optional follow-up.
  3. Write the failing test first for the next small behavior (including its error path), then write the minimal code to pass it, then refactor. Repeat per behavior — never write a whole layer before any test.
  4. Pick the layer. Keep transport (HTTP/GraphQL), application (use cases), and infrastructure (DB, external APIs) separated. Business rules must not import framework or DB types directly. Shared contracts live in one shared module.
  5. Validate at the boundary. Parse and validate all external input (body, params, headers) before it reaches business logic. Reject early with clear errors.
  6. Make failure explicit. Return typed/structured errors with correct status codes via the central error handler. Map upstream failures (e.g. a 404 from an external API) to the intended response — never let EnsureSuccess-style throws become an accidental 500. Never swallow exceptions silently.
  7. Document the contract as you implement: doc comments + API annotations.
  8. Add observability: structured logs with a request/correlation id, metrics on key paths, traces for cross-service calls.
  9. Run the Definition of Done gate before declaring complete.

Architecture & file organization (enforced)

  • Dependency direction: transport → application → domain; infrastructure implements interfaces defined by the inner layers. Inner layers never depend on outer ones. Business rules don't import framework/DB/HTTP types.
  • One shared source of truth for contracts. Request/response DTOs shared between producer and consumer (e.g. API and a client) live in a single shared module/package both reference. Copying a model into two projects is a defect, not a style choice.
  • One type per file, file named after the type, placed in the folder matching its layer/aggregate. Do not dump many classes/types into a single file.
  • Anti-corruption boundary: keep external/raw DTOs (third-party API shapes) separate from your own domain/response models, and map between them — don't leak upstream shapes through your API.
  • Right-size it. For a small service, layers can be folders within one project; for larger ones, separate projects/modules. Either way, the dependency direction and the "shared contracts in one place" rule still hold.

API design checklist

  • Consistent resource naming and pluralization (/users/{id}/orders).
  • Correct status codes: 200/201/204, 400/401/403/404/409/422, 429, 5xx.
  • Pagination, filtering and sorting use query params with sane defaults and hard limits.
  • Idempotency keys for unsafe retried operations (payments, webhooks).
  • Versioning strategy decided up front (/v1, header, or media type).
  • Responses are stable contracts: additive changes only, deprecate before removing.

Database checklist

  • Index the columns you filter/join/sort on; verify with EXPLAIN ANALYZE.
  • Avoid N+1: batch, join, or use dataloaders.
  • Use transactions for multi-statement writes; keep them short.
  • Migrations are forward-only, reversible, and tested on a copy of prod data.
  • Never trust application-level uniqueness — enforce constraints in the DB.
  • Paginate with keyset/cursor pagination for large tables, not OFFSET.

Security checklist

  • Authentication and authorization are separate concerns — check both.
  • Validate and sanitize all input; use parameterized queries (no string-built SQL).
  • Secrets come from the environment/secret manager, never the repo.
  • Rate-limit and throttle public endpoints.
  • Hash passwords with bcrypt/argon2; never log tokens, passwords or PII.
  • Set least-privilege DB and service-account permissions.

Performance checklist

  • Measure before optimizing; identify the actual bottleneck (DB, CPU, IO, network).
  • Cache read-heavy data with explicit invalidation and TTLs.
  • Move slow/external work to background jobs or queues.
  • Use connection pooling; tune pool size to the DB, not arbitrarily high.
  • Stream large payloads instead of buffering them in memory.

Anti-patterns to flag in review

  • Shipping code with no tests (the most common failure — never acceptable).
  • Untested infrastructure layer — HTTP clients / repositories left near 0% because they "just call an external API". Mock the transport and test them.
  • Low branch coverage on error handling — exception middleware, catch, and if/else arms not exercised. Happy-path-only tests inflate line coverage while branches stay uncovered.
  • Coverage padded with assertion-free tests that call code without verifying behavior, just to hit a number.
  • Duplicated DTOs/contracts across projects instead of a shared module.
  • Many types crammed into one file instead of one type per file.
  • Dead error-handling branches, e.g. a NotFound return that can never run because an upstream call throws first on a 404.
  • Missing contract docs / API annotations on public endpoints and interfaces.
  • Hardcoded config (URLs, secrets, timeouts, CORS, TTLs) in source.
  • Business logic inside controllers/route handlers.
  • Catch-all try/catch that hides the real error.
  • Unbounded queries (SELECT * without limit, missing pagination).
  • Auth checks duplicated inconsistently across endpoints.
  • Mutating shared state without transactions or locks.
  • Synchronous calls to slow third-party APIs in the request path.

Output expectations

When implementing, ship the endpoint/function together with its tests (happy + error paths), shared contracts in one place, one type per file, contract docs, and centralized error handling — then state the Definition of Done checklist with each item marked, including the measured coverage numbers (line and branch, per layer). Do not claim completion with unchecked items or with any layer under 90%; if something was intentionally skipped, call it out as a known gap. When reviewing, return findings grouped by severity (blocker / should-fix / nit) with concrete fixes. Always answer in the user's language.

Source & license

This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.

Install and usage instructions live in the source repository linked above.

Reviews

No reviews yet — be the first.

Versions

  • v0.1.0 Imported from the upstream source.