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.
Resources
1Install
npx skillscat add truongnat/agentic-sdlc/senior-backend Install via the SkillsCat registry.
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
- Explicit Boundaries: Separate business logic from infrastructure. Business rules (Domain) should never know about your database or web framework.
- Defensive Programming: Validate every input, handle every error explicitly, and never trust external systems.
- Data-Driven Performance: Optimization must be based on profiling and understanding of the underlying storage engine.
- 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:
- Sanitize: Validating inputs against strict schemas (Pydantic/Zod).
- Authorize: Checking not just if a user is logged in, but if they own the resource.
- 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
- ❌ Leaky Abstractions: Passing database models (e.g., SQLAlchemy/TypeORM objects) into the Domain layer.
- ❌ Logic in Controllers: Writing business rules directly in your router handlers.
- ❌ Silent Failures:
try...except: passor ignoring Result errors. - ❌ Fat Services: Single service classes with thousands of lines of logic. Split into Use Case classes.
- ❌ 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.