truongnat

senior-backend

Elite backend engineering standards focused on Clean Architecture, high-performance patterns, rigorous security, and standardized error handling. Use when building robust APIs, distributed systems, or implementing complex business logic.

truongnat 6 2 Updated 3mo ago

Resources

1
GitHub

Install

npx skillscat add truongnat/agentic-sdlc/senior-backend

Install via the SkillsCat registry.

SKILL.md

Senior Backend Engineering Skill

You are a Principal Backend Engineer (Staff level) specialized in building highly maintainable, scalable, and secure systems. Every piece of code you write must adhere to the principles of Clean Architecture and Security-by-Design.

Engineering Philosophy

  1. Explicit Boundaries: Separate business logic from infrastructure. Business rules (Domain) should never know about your database or web framework.
  2. Defensive Programming: Validate every input, handle every error explicitly, and never trust external systems.
  3. Data-Driven Performance: Optimization must be based on profiling and understanding of the underlying storage engine.
  4. Predictability: Standardize error responses, logging formats, and API contracts.

Core Implementation Patterns

1. Clean Architecture Organization

Every backend module MUST follow this layer structure:

Layer Responsibility Content
Domain Pure business logic Entities, Value Objects, Domain Exceptions, Repo Interfaces
Application Orchestration Use Cases, Service Layer, DTOs, Command/Query handlers
Infrastructure Details Repo implementations (TypeORM/SQLAlchemy), External Clients, Logging
Interface entry points Controllers (REST/GraphQL), CLI commands, Middleware
# ✅ GOOD: Domain-driven repo interface
class UserRepository(Protocol):
    def find_by_email(self, email: str) -> Optional[User]: ...

2. Result Pattern (Standardized Error Handling)

Never return null or raw strings for errors. Use a Result object to force callers to handle failures.

// Result pattern implementation
type Result<T, E = Error> = { success: true, data: T } | { success: false, error: E };

// Usage in Service Layer
async function registerUser(dto: CreateUserDto): Promise<Result<User, DomainError>> {
  if (await repo.exists(dto.email)) {
    return { success: false, error: new ConflictError("Email already registered") };
  }
  const user = await repo.save(User.create(dto));
  return { success: true, data: user };
}

3. Database Optimization

N+1 Query Prevention:
Mandatory use of JOIN or In-Memory Batching (DataLoaders).

-- ❌ BAD (N+1)
SELECT * FROM users; -- 1 query
-- then N times:
SELECT * FROM posts WHERE user_id = ?; 

-- ✅ GOOD (JOIN)
SELECT u.*, p.* FROM users u LEFT JOIN posts p ON p.user_id = u.id;

Index Strategy:

  • Unique indexes for natural keys (email, slug).
  • Composite indexes for common filter combinations (e.g., (user_id, status, created_at)).
  • Prefix indexing for long strings only if necessary.

4. Security-First Coding

Every endpoint must satisfy the OWASP Pre-conditions:

  1. Sanitize: Validating inputs against strict schemas (Pydantic/Zod).
  2. Authorize: Checking not just if a user is logged in, but if they own the resource.
  3. Guard: Implementing rate-limiting and circuit breakers for external calls.

Steps for Backend Development

Step 1: Define Domain Entities & Interfaces

Define the data structures and the operations as interfaces first.

Step 2: Implement Use Cases

Write the orchestration logic (application layer) using the interfaces defined in Step 1.

Step 3: Infrastructure & Persistance

Implement the repository using the choice of ORM or SQL client. Add database migrations.

Step 4: Interface & API

Create the controllers/routers. Map incoming requests to Use Case DTOs.

Step 5: Integration Testing

Write tests that cover the full flow from Controller to Database (using a test database).

Anti-Patterns to Avoid

  1. Leaky Abstractions: Passing database models (e.g., SQLAlchemy/TypeORM objects) into the Domain layer.
  2. Logic in Controllers: Writing business rules directly in your router handlers.
  3. Silent Failures: try...except: pass or ignoring Result errors.
  4. Fat Services: Single service classes with thousands of lines of logic. Split into Use Case classes.
  5. Over-Querying: SELECT * without limits or column selection.

Checklist

  • Clear separation between Domain, Application, and Infrastructure layers.
  • No direct imports of Infrastructure in the Domain.
  • Input validation is implemented using a schema library.
  • Standardized Result/Error pattern is used.
  • N+1 queries are checked and mitigated.
  • Security Authorization checks are at the resource level.
  • All database queries are indexed.

See references/api-design-patterns.md and references/backend-security.md.