Agent skill
backend-patterns-skill
Install this agent skill to your Project
npx add-skill https://github.com/majiayu000/claude-skill-registry/tree/main/skills/other/backend-patterns-skill
SKILL.md
Backend Patterns Skill
=== PURPOSE ===
Procedures for implementing backend architectural patterns.
=== USED BY ===
| Agent | Purpose |
|---|---|
| @agent(backend-engineer) @ref(CB-AGENT-BACKEND-001) | Primary skill for architecture |
=== PATTERN: Layered Architecture ===
Layers (top to bottom):
┌─────────────────────────┐
│ Controllers/Routes │ ← HTTP handling
├─────────────────────────┤
│ Services │ ← Business logic
├─────────────────────────┤
│ Repositories │ ← Data access
├─────────────────────────┤
│ Database │ ← Persistence
└─────────────────────────┘
Rules:
- Each layer only calls the layer below
- Controllers handle HTTP, call services
- Services contain business logic, call repositories
- Repositories handle data access only
=== PATTERN: Service Layer ===
Structure:
// services/user.service.ts
export class UserService {
constructor(
private userRepository: UserRepository,
private emailService: EmailService
) {}
async createUser(data: CreateUserDto): Promise<User> {
// Business logic here
const existing = await this.userRepository.findByEmail(data.email);
if (existing) {
throw new ConflictError('Email already registered');
}
const user = await this.userRepository.create(data);
await this.emailService.sendWelcome(user.email);
return user;
}
}
Guidelines:
- One service per domain entity/concept
- Services can call other services
- All business rules live in services
- Services are testable in isolation
=== PATTERN: Repository Pattern ===
Interface:
interface Repository<T> {
findById(id: string): Promise<T | null>;
findAll(options?: QueryOptions): Promise<T[]>;
create(data: Partial<T>): Promise<T>;
update(id: string, data: Partial<T>): Promise<T>;
delete(id: string): Promise<void>;
}
Implementation:
export class UserRepository implements Repository<User> {
constructor(private db: Database) {}
async findById(id: string): Promise<User | null> {
return this.db.user.findUnique({ where: { id } });
}
async findByEmail(email: string): Promise<User | null> {
return this.db.user.findUnique({ where: { email } });
}
// ... other methods
}
=== PATTERN: Dependency Injection ===
Manual DI:
// Bootstrap
const db = new Database();
const userRepository = new UserRepository(db);
const emailService = new EmailService();
const userService = new UserService(userRepository, emailService);
const userController = new UserController(userService);
Container-based DI (example with tsyringe):
@injectable()
export class UserService {
constructor(
@inject('UserRepository') private userRepository: UserRepository,
@inject('EmailService') private emailService: EmailService
) {}
}
=== PATTERN: Error Handling ===
Custom Error Classes:
export class AppError extends Error {
constructor(
public code: string,
public message: string,
public statusCode: number = 500
) {
super(message);
}
}
export class NotFoundError extends AppError {
constructor(resource: string) {
super('NOT_FOUND', `${resource} not found`, 404);
}
}
export class ValidationError extends AppError {
constructor(message: string, public details?: unknown) {
super('VALIDATION_ERROR', message, 400);
}
}
export class ConflictError extends AppError {
constructor(message: string) {
super('CONFLICT', message, 409);
}
}
=== PATTERN: Middleware Chain ===
Order (typical):
app.use(cors()); // 1. CORS
app.use(helmet()); // 2. Security headers
app.use(morgan('combined')); // 3. Logging
app.use(express.json()); // 4. Body parsing
app.use(rateLimit()); // 5. Rate limiting
app.use(authenticate); // 6. Authentication (where needed)
app.use('/api', routes); // 7. Routes
app.use(errorHandler); // 8. Error handling (last)
=== PATTERN: Background Jobs ===
Job Queue Pattern:
// Define job
interface EmailJob {
type: 'SEND_EMAIL';
payload: {
to: string;
template: string;
data: Record<string, unknown>;
};
}
// Enqueue
await jobQueue.add({
type: 'SEND_EMAIL',
payload: { to: user.email, template: 'welcome', data: { name: user.name } }
});
// Process
jobQueue.process('SEND_EMAIL', async (job) => {
await emailService.send(job.payload);
});
=== PATTERN: Caching ===
Cache-Aside Pattern:
async function getUser(id: string): Promise<User> {
const cacheKey = `user:${id}`;
// Try cache first
const cached = await cache.get(cacheKey);
if (cached) return JSON.parse(cached);
// Miss - fetch from DB
const user = await userRepository.findById(id);
if (!user) throw new NotFoundError('User');
// Store in cache
await cache.set(cacheKey, JSON.stringify(user), 'EX', 3600);
return user;
}
Cache Invalidation:
async function updateUser(id: string, data: UpdateUserDto): Promise<User> {
const user = await userRepository.update(id, data);
// Invalidate cache
await cache.del(`user:${id}`);
return user;
}
=== RELATED SKILLS ===
| Skill | Relationship |
|---|---|
| @skill(api-development) | API implementation |
| @skill(schema-design) | Data model alignment |
Recommended Agent Skills
Expand your agent's capabilities with these related and highly-rated skills.
agent-ops-spec
Manage specification documents in .agent/specs/. Use when user provides requirements, acceptance criteria, or feature descriptions that need to be tracked and validated against implementation.
agent-ops-state
Maintain .agent state files. Use at session start, after meaningful steps, and before concluding: read/update constitution/memory/focus/issues/baseline consistently.
agent-ops-spec
Manage specification documents in .agent/specs/. Use when user provides requirements, acceptance criteria, or feature descriptions that need to be tracked and validated against implementation.
agent-ops-testing
Test strategy, execution, and coverage analysis. Use when designing tests, running test suites, or analyzing test results beyond baseline checks.
agent-ops-testing
Test strategy, execution, and coverage analysis. Use when designing tests, running test suites, or analyzing test results beyond baseline checks.
agent-ops-state
Maintain .agent state files. Use at session start, after meaningful steps, and before concluding: read/update constitution/memory/focus/issues/baseline consistently.
Didn't find tool you were looking for?