agentleFS
egagofuregagofur/ai-engineering-loop/.claude/skills/backend-development/SKILL.md

backend-development

Skill2 starsChanged 8 days agoMITView on GitHub

Framework-agnostic backend best practices for clean code, naming, queries/databases, REST APIs, errors, security, performance, scalability, testing, and structure. Trigger on backend implementation, architecture, code quality, naming, magic values, complex conditionals, query optimization, caching, error handling, or security tasks.

24 other projects use a version of this.

Adopted by

Most recently taken up by

Used with

Projects with it also use Problem-Solving Techniques, llm-application-dev and 10 more.

Other files people use alongside this one.

Files found in the same public projects as a version of this one, more often than they turn up anywhere else. Each project counts once, large collections count for less, and this file's own repository is left out.
  • truongtv22Skill

    Problem-Solving Techniques

    Apply systematic problem-solving techniques for complexity spirals (simplification cascades), innovation blocks (collision-zone thinking), recurring patterns (meta-pattern recognition), assumption constraints (inversion exercise), scale uncertainty (scale game), and dispatch when stuck. Techniques derived from Microsoft Amplifier project patterns adapted for immediate application.

    Also in 5 projects that use this

  • pepebot-spaceSkill

    llm-application-dev

    Building applications with Large Language Models - prompt engineering, RAG patterns, and LLM integration. Use for AI-powered features, chatbots, or LLM-based automation.

    Also in 4 projects that use this

  • MoizIbnYousafSkill

    audit-library-health

    Use when checking the overall health of a skills library. Run doctor, validate, check for stale skills, and verify generated docs are in sync.

    Also in 3 projects that use this

  • MoizIbnYousafSkill

    browse-and-evaluate

    Use when exploring the ai-agent-skills catalog to find, compare, and evaluate skills before installing. Always use --fields to limit output size and --dry-run before committing to an install.

    Also in 3 projects that use this

  • OpenAnalystIncSkill

    markdown-novel-viewer

    Also in 3 projects that use this

  • +7 more from MoizIbnYousaf

The file

Show its rules and text

We split this skill into the rules it gives an agent

30 rules. 0 are common, 22 are distinctive, and 8 are very specific to this project.

  • 0

    Common

    Most of the 7 edited versions we read keep these.

  • 22

    Distinctive

    This author's own choices. Worth a look.

  • 8

    Very specific

    Tied to their project's names, files or tools. Probably skip.

  • Common
  • Distinctive
  • Very specific
  1. Distinctive:

    Prefer the project’s established patterns when they are coherent.

    line 15
  2. Distinctive:

    Do not introduce speculative architecture.

    line 16
  3. Distinctive:

    Read reference files only when depth is needed:

    line 17
  4. Distinctive:

    Every function, class, and module should have one reason to exist.

    line 28
  5. Very specific:

    Avoid ambiguous booleans like active, verified, enabled, permission, or status unless the type is intentionally not boolean.

    line 56
  6. Distinctive:

    Do not abstract merely because code looks similar twice.

    line 71
  7. Distinctive:

    Prefer straightforward solutions.

    line 72
  8. Distinctive:

    Keep comments for intent, protocol details, warning of consequences, public API docs, legal headers, and living TODOs.

    line 124
  9. Distinctive:

    Use transactions for multi-step writes.

    line 162
  10. Distinctive:

    Use connection pools sized to expected concurrency.

    line 163
  11. Very specific:

    Read references/query-and-database-best-practices.md for schema, query, pagination, migration, and pool-sizing details.

    line 165
  12. Very specific:

    Use resource nouns, not verbs: POST /orders, not /create-order.

    line 173
  13. Very specific:

    Use plural collections: /users, /orders, /products.

    line 174
  14. Distinctive:

    Keep response envelopes consistent for success and error.

    line 176
  15. Very specific:

    Read references/api-design-guidelines.md for endpoint patterns, envelopes, pagination, filtering, bulk operations, and versioning.

    line 182
  16. Distinctive:

    Treat error paths with the same care as success paths.

    line 188
  17. Distinctive:

    Use consistent error shape: HTTP status, machine-readable code, human-readable message, optional details.

    line 190
  18. Distinctive:

    Do not expose stack traces, internal paths, raw SQL errors, secret values, or implementation details.

    line 191
  19. Very specific:

    Use specific status codes: 400, 401, 403, 404, 409, 422, 429, 500, 502, 503.

    line 200
  20. Distinctive:

    Use parameterized queries or query builders.

    line 211
  21. Distinctive:

    Never rely solely on frontend checks.

    line 215
  22. Very specific:

    Read references/security-checklist.md for auth, authorization, validation, headers, dependency security, and vulnerability prevention.

    line 219
  23. Distinctive:

    Keep services stateless; externalize session/state to Redis/database when needed.

    line 227
  24. Distinctive:

    Use eager loading when related data is always needed.

    line 229
  25. Distinctive:

    Use bulk operations for mass writes/deletes.

    line 230
  26. Distinctive:

    Use layers unless the operation is trivially simple:

    line 239
  27. Very specific:

    Use dependency injection; avoid new inside services for dependencies.

    line 250
  28. Distinctive:

    Test behavior and business rules, not framework internals.

    line 260
  29. Distinctive:

    Avoid testing private methods, simple getters, third-party behavior, and framework plumbing unless your code configures it in a risky way.

    line 268
  30. Distinctive:

    Use factories/builders for test data.

    line 272

“Common” is measured: kept by at least 6 in 10 of the 7 edited versions of this file we could read. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
SKILL.md

Backend Development Guidelines

Universal principles for reliable, maintainable, performant backends — regardless of framework or language.

Framework-specific conventions in CLAUDE.md, AGENTS.md, README files, or project docs take precedence for implementation details. This skill governs the underlying engineering principles.

How to use this skill

  • Apply these rules during backend implementation, review, refactoring, architecture, naming, database, API, error-handling, security, performance, and testing work.
  • Prefer the project’s established patterns when they are coherent. Use this skill to improve unclear, unsafe, or over-complex code.
  • Do not introduce speculative architecture. Fix the rule causing the problem, with the smallest coherent design.
  • Read reference files only when depth is needed:
    • references/query-and-database-best-practices.md
    • references/api-design-guidelines.md
    • references/security-checklist.md

1. Clean Code Principles

Single Responsibility

Every function, class, and module should have one reason to exist. If you need “and” to describe it — validates input and saves to database and sends notification — split it.

  • Functions do one thing. A data fetcher should not format presentation output.
  • Services/classes own one domain concept. UserService handles user logic, not email delivery.
  • Modules encapsulate one bounded context. Cross-module access flows through well-defined interfaces.

Meaningful Names

Names reveal intent without requiring a comment.

  • Variables: activeUserCount, invoiceDueDate, orderItems.
  • Functions: verb-first and specific, e.g. calculateShippingCost, archiveExpiredCoupons, validateEmailFormat.
  • Classes/types: role-suffixed nouns, e.g. UserService, OrderRepository, PaymentController, ProductDto.
  • Abbreviations: only universally understood ones like id, url, dto, http.

Boolean naming

Boolean names must read as yes/no propositions. Use prefixes that reveal the type and intent:

PrefixReads asExample
isIs it in this state?isActive, isEmailVerified
hasDoes it own this?hasPermission, hasSubscription
canIs it allowed or able?canRetry, canRefund
shouldOught it happen?shouldNotify, shouldRetry
wasDid it happen?wasDeleted, wasCharged
willIs it going to happen?willExpire, willRenew

Avoid ambiguous booleans like active, verified, enabled, permission, or status unless the type is intentionally not boolean.

// Bad: string? number? boolean?
const active = user.status
const verification = checkEmail(email)

// Good: yes/no at a glance
const isActive = user.status === 'active'
const isEmailVerified = checkEmailVerification(email)

DRY, KISS, YAGNI

  • Extract repeated logic when changing one copy would force changes everywhere.
  • Do not abstract merely because code looks similar twice; similar code may diverge.
  • Prefer straightforward solutions. Patterns and abstractions must earn their complexity.
  • Build for today’s requirements. Add extension points when the requirement arrives.

Guard clauses and early returns

Handle edge cases at the top and return early. Keep the happy path at the lowest indentation level.

Extract complex conditions

A condition should read as intent, not mechanics. Name the rule before testing it.

const meetsAgeRequirement = user.age >= MIN_AGE
const isIdentityVerified = user.kycStatus === 'verified'
const isInGoodStanding = !user.isBanned && user.region !== 'restricted'
const hasPremiumAccess = user.accountType === 'premium'
  || user.loyaltyPoints > LOYALTY_THRESHOLD

const isEligibleForAccess = meetsAgeRequirement
  && isIdentityVerified
  && isInGoodStanding
  && hasPremiumAccess

if (isEligibleForAccess) {
  grantAccess()
}

Rule of thumb: if the reader must parse operators, extract a named variable. This applies to a single domain comparison too when the mechanism hides the business rule.

Function size

Aim for 20–30 lines. If a function exceeds 40 lines, look for extraction opportunities. A block that needs a section comment is a candidate for its own function.

No magic numbers or strings

Extract domain-meaningful literals into named constants: status codes, thresholds, retry counts, timeouts, role IDs, page limits.

const ROLE_ADMIN = 3
const ONE_DAY_MS = 24 * 60 * 60 * 1000
const MAX_ITEMS_PER_ORDER = 50

const isAdmin = user.role === ROLE_ADMIN
const isSessionStale = Date.now() - lastLogin > ONE_DAY_MS
const exceedsItemLimit = order.items.length > MAX_ITEMS_PER_ORDER

Comments

A comment is often a failure to make the code say it itself. Before adding one, try renaming or extracting.

Keep comments for intent, protocol details, warning of consequences, public API docs, legal headers, and living TODOs. Delete comments that restate code, drift out of date, journal changes, attribute authors, or preserve commented-out code.

Command-Query Separation

Functions that return data should avoid side effects. Functions that mutate state should make mutation explicit. Reads are safe; writes are deliberate.


2. Naming Conventions

ContextConventionExamples
Variables, parametersDescriptive nouns, language-standard casinguserId, orderItems, isValid
Functions, methodsVerb-firstgetUser, createOrder, validateInput, isExpired
Classes, typesPascalCase nouns, role suffixUserService, OrderRepository, PaymentController
ConstantsUPPER_SNAKE_CASEMAX_RETRY_COUNT, DEFAULT_PAGE_SIZE
Database columnssnake_casecreated_at, user_id, is_active
Database tablessnake_case pluralusers, order_items, payment_transactions
API endpointslowercase plural nouns, kebab-case/users, /order-items
Enum valuesUPPER_SNAKE_CASE or language conventionPENDING, IN_PROGRESS

Foreign keys: {referenced_table_singular}_id, e.g. user_id.

Boolean columns: is_active, is_verified, has_subscription.

Timestamp columns: suffix _at, e.g. created_at, updated_at, deleted_at, expires_at.


3. Query and Database Best Practices

Poor query patterns are a common backend bottleneck.

  • Prevent N+1 queries with joins, eager loading, or batch loading.
  • Select only needed columns. Avoid SELECT * in application queries.
  • Index foreign keys and frequent WHERE / ORDER BY fields.
  • Composite indexes follow leftmost prefix rules.
  • Paginate list endpoints; never return unbounded lists.
  • Use transactions for multi-step writes. Keep transactions short.
  • Use connection pools sized to expected concurrency.

Read references/query-and-database-best-practices.md for schema, query, pagination, migration, and pool-sizing details.


4. API Design Principles

A good API is consistent and predictable.

  • Use resource nouns, not verbs: POST /orders, not /create-order.
  • Use plural collections: /users, /orders, /products.
  • Nest sub-resources at most two levels; flatten deeper models.
  • Keep response envelopes consistent for success and error.
  • Version breaking API contracts explicitly, usually /v1, /v2.
  • Validate filters and sort fields against allow-lists.
  • Include pagination metadata.
  • For long-running work, return 202 Accepted with a task/status resource.

Read references/api-design-guidelines.md for endpoint patterns, envelopes, pagination, filtering, bulk operations, and versioning.


5. Error Handling

Treat error paths with the same care as success paths.

  • Use consistent error shape: HTTP status, machine-readable code, human-readable message, optional details.
  • Do not expose stack traces, internal paths, raw SQL errors, secret values, or implementation details.
  • Validate at the API boundary and fail fast.
  • User-facing messages must answer what went wrong and what to do next.
Bad: ValidationError: field 'shipping_zone_id' violates constraint fk_order_zone
Good: Cannot save this order. The selected shipping zone is no longer available. Choose a different shipping zone and save again.

Use specific status codes: 400, 401, 403, 404, 409, 422, 429, 500, 502, 503.

Structured logs should include request ID, user ID when available, action, and sanitized error context. Never log passwords, tokens, API keys, or PII.


6. Security

Security is a design constraint.

  • Validate all external input at boundaries.
  • Use parameterized queries or query builders; never concatenate user input into SQL, shell commands, or template expressions.
  • Store secrets in env vars or secret managers, never source code.
  • Hash passwords with bcrypt, argon2, or scrypt.
  • Enforce authorization at API boundaries and verify resource ownership.
  • Never rely solely on frontend checks.
  • Mask sensitive fields in API responses and logs.
  • Use HTTPS everywhere.

Read references/security-checklist.md for auth, authorization, validation, headers, dependency security, and vulnerability prevention.


7. Performance and Scalability

Design for predictable performance under load.

  • Keep services stateless; externalize session/state to Redis/database when needed.
  • Cache expensive operations with explicit invalidation strategy.
  • Use eager loading when related data is always needed; lazy loading only when rare and safe.
  • Use bulk operations for mass writes/deletes.
  • Offload long-running work to queues/background jobs.
  • Enable response compression.
  • Limit request body size and paginate/stream large payloads.

8. Code Organization

Use layers unless the operation is trivially simple:

  1. Controller/handler: request parsing, validation, response mapping. No business logic.
  2. Service: business logic and orchestration. Framework-agnostic where possible.
  3. Repository/data access: persistence and schema-aware queries.

Rules:

  • Services should not know HTTP status codes.
  • Controllers should not contain SQL.
  • Repositories should not enforce business workflows.
  • Use dependency injection; avoid new inside services for dependencies.
  • Domain modules own their entities, DTOs, services, and repositories.
  • Cross-module communication goes through service interfaces.
  • Shared utilities must be truly shared; avoid tangled abstractions.
  • Externalize configuration into typed config objects.

9. Testing Strategy

Test behavior and business rules, not framework internals.

  • Unit tests: business logic and edge cases.
  • Integration tests: repositories, real database behavior, HTTP endpoints.
  • E2E tests: critical flows only.

Cover happy paths, empty inputs, boundary values, invalid inputs, authorization failures, and business rule violations.

Avoid testing private methods, simple getters, third-party behavior, and framework plumbing unless your code configures it in a risky way.

Name tests by scenario and outcome: should return 404 when user does not exist.

Use factories/builders for test data. Each test owns its setup and cleanup.

Download now (ZIP)

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
What did you use it for? e.g. Reviewing pull requests in a Rails app

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.