KS
Killer-Skills

backend-patterns — how to use backend-patterns how to use backend-patterns, backend-patterns for Node.js, API design best practices, backend-patterns vs REST, backend-patterns setup guide, scalable server-side applications, GraphQL API endpoint design, database optimization techniques

Verified
v1.0.0
GitHub

About this Skill

Essential for Backend Engineering Agents specializing in Node.js ecosystem API development and database optimization. backend-patterns is a set of techniques for designing and implementing efficient server-side architectures, including REST and GraphQL API endpoints

Features

Designs REST and GraphQL API endpoints for Node.js, Express, and Next.js
Optimizes database queries using N+1, indexing, and connection pooling
Implements caching using Redis, in-memory, and HTTP cache headers
Structures error handling and validation for APIs
Sets up background jobs and async processing for efficient server-side operations

# Core Topics

affaan-m affaan-m
[62.0k]
[7678]
Updated: 3/6/2026

Quality Score

Top 5%
86
Excellent
Based on code quality & docs
Installation
SYS Universal Install (Auto-Detect)
Cursor IDE Windsurf IDE VS Code IDE
> npx killer-skills add affaan-m/everything-claude-code/backend-patterns

Agent Capability Analysis

The backend-patterns MCP Server by affaan-m is an open-source Categories.official integration for Claude and other AI agents, enabling seamless task automation and capability expansion. Optimized for how to use backend-patterns, backend-patterns for Node.js, API design best practices.

Ideal Agent Persona

Essential for Backend Engineering Agents specializing in Node.js ecosystem API development and database optimization.

Core Value

Provides comprehensive backend architecture patterns for implementing repository, service, and controller layers in Express and Next.js API routes. Enables advanced database optimization techniques including N+1 query resolution, indexing strategies, and Redis caching implementation.

Capabilities Granted for backend-patterns MCP Server

Designing REST or GraphQL API endpoints
Optimizing database queries and connection pooling
Implementing middleware for authentication and logging
Structuring error handling and validation for server-side applications
Setting up background jobs and async processing systems

! Prerequisites & Limits

  • Node.js/Express/Next.js specific implementation
  • Requires database integration knowledge
  • Caching implementation depends on external services like Redis
Project
SKILL.md
13.3 KB
.cursorrules
1.2 KB
package.json
240 B
Ready
UTF-8
SKILL.md
Readonly

Backend Development Patterns

Backend architecture patterns and best practices for scalable server-side applications.

When to Activate

  • Designing REST or GraphQL API endpoints
  • Implementing repository, service, or controller layers
  • Optimizing database queries (N+1, indexing, connection pooling)
  • Adding caching (Redis, in-memory, HTTP cache headers)
  • Setting up background jobs or async processing
  • Structuring error handling and validation for APIs
  • Building middleware (auth, logging, rate limiting)

API Design Patterns

RESTful API Structure

typescript
1// ✅ Resource-based URLs 2GET /api/markets # List resources 3GET /api/markets/:id # Get single resource 4POST /api/markets # Create resource 5PUT /api/markets/:id # Replace resource 6PATCH /api/markets/:id # Update resource 7DELETE /api/markets/:id # Delete resource 8 9// ✅ Query parameters for filtering, sorting, pagination 10GET /api/markets?status=active&sort=volume&limit=20&offset=0

Repository Pattern

typescript
1// Abstract data access logic 2interface MarketRepository { 3 findAll(filters?: MarketFilters): Promise<Market[]> 4 findById(id: string): Promise<Market | null> 5 create(data: CreateMarketDto): Promise<Market> 6 update(id: string, data: UpdateMarketDto): Promise<Market> 7 delete(id: string): Promise<void> 8} 9 10class SupabaseMarketRepository implements MarketRepository { 11 async findAll(filters?: MarketFilters): Promise<Market[]> { 12 let query = supabase.from('markets').select('*') 13 14 if (filters?.status) { 15 query = query.eq('status', filters.status) 16 } 17 18 if (filters?.limit) { 19 query = query.limit(filters.limit) 20 } 21 22 const { data, error } = await query 23 24 if (error) throw new Error(error.message) 25 return data 26 } 27 28 // Other methods... 29}

Service Layer Pattern

typescript
1// Business logic separated from data access 2class MarketService { 3 constructor(private marketRepo: MarketRepository) {} 4 5 async searchMarkets(query: string, limit: number = 10): Promise<Market[]> { 6 // Business logic 7 const embedding = await generateEmbedding(query) 8 const results = await this.vectorSearch(embedding, limit) 9 10 // Fetch full data 11 const markets = await this.marketRepo.findByIds(results.map(r => r.id)) 12 13 // Sort by similarity 14 return markets.sort((a, b) => { 15 const scoreA = results.find(r => r.id === a.id)?.score || 0 16 const scoreB = results.find(r => r.id === b.id)?.score || 0 17 return scoreA - scoreB 18 }) 19 } 20 21 private async vectorSearch(embedding: number[], limit: number) { 22 // Vector search implementation 23 } 24}

Middleware Pattern

typescript
1// Request/response processing pipeline 2export function withAuth(handler: NextApiHandler): NextApiHandler { 3 return async (req, res) => { 4 const token = req.headers.authorization?.replace('Bearer ', '') 5 6 if (!token) { 7 return res.status(401).json({ error: 'Unauthorized' }) 8 } 9 10 try { 11 const user = await verifyToken(token) 12 req.user = user 13 return handler(req, res) 14 } catch (error) { 15 return res.status(401).json({ error: 'Invalid token' }) 16 } 17 } 18} 19 20// Usage 21export default withAuth(async (req, res) => { 22 // Handler has access to req.user 23})

Database Patterns

Query Optimization

typescript
1// ✅ GOOD: Select only needed columns 2const { data } = await supabase 3 .from('markets') 4 .select('id, name, status, volume') 5 .eq('status', 'active') 6 .order('volume', { ascending: false }) 7 .limit(10) 8 9// ❌ BAD: Select everything 10const { data } = await supabase 11 .from('markets') 12 .select('*')

N+1 Query Prevention

typescript
1// ❌ BAD: N+1 query problem 2const markets = await getMarkets() 3for (const market of markets) { 4 market.creator = await getUser(market.creator_id) // N queries 5} 6 7// ✅ GOOD: Batch fetch 8const markets = await getMarkets() 9const creatorIds = markets.map(m => m.creator_id) 10const creators = await getUsers(creatorIds) // 1 query 11const creatorMap = new Map(creators.map(c => [c.id, c])) 12 13markets.forEach(market => { 14 market.creator = creatorMap.get(market.creator_id) 15})

Transaction Pattern

typescript
1async function createMarketWithPosition( 2 marketData: CreateMarketDto, 3 positionData: CreatePositionDto 4) { 5 // Use Supabase transaction 6 const { data, error } = await supabase.rpc('create_market_with_position', { 7 market_data: marketData, 8 position_data: positionData 9 }) 10 11 if (error) throw new Error('Transaction failed') 12 return data 13} 14 15// SQL function in Supabase 16CREATE OR REPLACE FUNCTION create_market_with_position( 17 market_data jsonb, 18 position_data jsonb 19) 20RETURNS jsonb 21LANGUAGE plpgsql 22AS $$ 23BEGIN 24 -- Start transaction automatically 25 INSERT INTO markets VALUES (market_data); 26 INSERT INTO positions VALUES (position_data); 27 RETURN jsonb_build_object('success', true); 28EXCEPTION 29 WHEN OTHERS THEN 30 -- Rollback happens automatically 31 RETURN jsonb_build_object('success', false, 'error', SQLERRM); 32END; 33$$;

Caching Strategies

Redis Caching Layer

typescript
1class CachedMarketRepository implements MarketRepository { 2 constructor( 3 private baseRepo: MarketRepository, 4 private redis: RedisClient 5 ) {} 6 7 async findById(id: string): Promise<Market | null> { 8 // Check cache first 9 const cached = await this.redis.get(`market:${id}`) 10 11 if (cached) { 12 return JSON.parse(cached) 13 } 14 15 // Cache miss - fetch from database 16 const market = await this.baseRepo.findById(id) 17 18 if (market) { 19 // Cache for 5 minutes 20 await this.redis.setex(`market:${id}`, 300, JSON.stringify(market)) 21 } 22 23 return market 24 } 25 26 async invalidateCache(id: string): Promise<void> { 27 await this.redis.del(`market:${id}`) 28 } 29}

Cache-Aside Pattern

typescript
1async function getMarketWithCache(id: string): Promise<Market> { 2 const cacheKey = `market:${id}` 3 4 // Try cache 5 const cached = await redis.get(cacheKey) 6 if (cached) return JSON.parse(cached) 7 8 // Cache miss - fetch from DB 9 const market = await db.markets.findUnique({ where: { id } }) 10 11 if (!market) throw new Error('Market not found') 12 13 // Update cache 14 await redis.setex(cacheKey, 300, JSON.stringify(market)) 15 16 return market 17}

Error Handling Patterns

Centralized Error Handler

typescript
1class ApiError extends Error { 2 constructor( 3 public statusCode: number, 4 public message: string, 5 public isOperational = true 6 ) { 7 super(message) 8 Object.setPrototypeOf(this, ApiError.prototype) 9 } 10} 11 12export function errorHandler(error: unknown, req: Request): Response { 13 if (error instanceof ApiError) { 14 return NextResponse.json({ 15 success: false, 16 error: error.message 17 }, { status: error.statusCode }) 18 } 19 20 if (error instanceof z.ZodError) { 21 return NextResponse.json({ 22 success: false, 23 error: 'Validation failed', 24 details: error.errors 25 }, { status: 400 }) 26 } 27 28 // Log unexpected errors 29 console.error('Unexpected error:', error) 30 31 return NextResponse.json({ 32 success: false, 33 error: 'Internal server error' 34 }, { status: 500 }) 35} 36 37// Usage 38export async function GET(request: Request) { 39 try { 40 const data = await fetchData() 41 return NextResponse.json({ success: true, data }) 42 } catch (error) { 43 return errorHandler(error, request) 44 } 45}

Retry with Exponential Backoff

typescript
1async function fetchWithRetry<T>( 2 fn: () => Promise<T>, 3 maxRetries = 3 4): Promise<T> { 5 let lastError: Error 6 7 for (let i = 0; i < maxRetries; i++) { 8 try { 9 return await fn() 10 } catch (error) { 11 lastError = error as Error 12 13 if (i < maxRetries - 1) { 14 // Exponential backoff: 1s, 2s, 4s 15 const delay = Math.pow(2, i) * 1000 16 await new Promise(resolve => setTimeout(resolve, delay)) 17 } 18 } 19 } 20 21 throw lastError! 22} 23 24// Usage 25const data = await fetchWithRetry(() => fetchFromAPI())

Authentication & Authorization

JWT Token Validation

typescript
1import jwt from 'jsonwebtoken' 2 3interface JWTPayload { 4 userId: string 5 email: string 6 role: 'admin' | 'user' 7} 8 9export function verifyToken(token: string): JWTPayload { 10 try { 11 const payload = jwt.verify(token, process.env.JWT_SECRET!) as JWTPayload 12 return payload 13 } catch (error) { 14 throw new ApiError(401, 'Invalid token') 15 } 16} 17 18export async function requireAuth(request: Request) { 19 const token = request.headers.get('authorization')?.replace('Bearer ', '') 20 21 if (!token) { 22 throw new ApiError(401, 'Missing authorization token') 23 } 24 25 return verifyToken(token) 26} 27 28// Usage in API route 29export async function GET(request: Request) { 30 const user = await requireAuth(request) 31 32 const data = await getDataForUser(user.userId) 33 34 return NextResponse.json({ success: true, data }) 35}

Role-Based Access Control

typescript
1type Permission = 'read' | 'write' | 'delete' | 'admin' 2 3interface User { 4 id: string 5 role: 'admin' | 'moderator' | 'user' 6} 7 8const rolePermissions: Record<User['role'], Permission[]> = { 9 admin: ['read', 'write', 'delete', 'admin'], 10 moderator: ['read', 'write', 'delete'], 11 user: ['read', 'write'] 12} 13 14export function hasPermission(user: User, permission: Permission): boolean { 15 return rolePermissions[user.role].includes(permission) 16} 17 18export function requirePermission(permission: Permission) { 19 return (handler: (request: Request, user: User) => Promise<Response>) => { 20 return async (request: Request) => { 21 const user = await requireAuth(request) 22 23 if (!hasPermission(user, permission)) { 24 throw new ApiError(403, 'Insufficient permissions') 25 } 26 27 return handler(request, user) 28 } 29 } 30} 31 32// Usage - HOF wraps the handler 33export const DELETE = requirePermission('delete')( 34 async (request: Request, user: User) => { 35 // Handler receives authenticated user with verified permission 36 return new Response('Deleted', { status: 200 }) 37 } 38)

Rate Limiting

Simple In-Memory Rate Limiter

typescript
1class RateLimiter { 2 private requests = new Map<string, number[]>() 3 4 async checkLimit( 5 identifier: string, 6 maxRequests: number, 7 windowMs: number 8 ): Promise<boolean> { 9 const now = Date.now() 10 const requests = this.requests.get(identifier) || [] 11 12 // Remove old requests outside window 13 const recentRequests = requests.filter(time => now - time < windowMs) 14 15 if (recentRequests.length >= maxRequests) { 16 return false // Rate limit exceeded 17 } 18 19 // Add current request 20 recentRequests.push(now) 21 this.requests.set(identifier, recentRequests) 22 23 return true 24 } 25} 26 27const limiter = new RateLimiter() 28 29export async function GET(request: Request) { 30 const ip = request.headers.get('x-forwarded-for') || 'unknown' 31 32 const allowed = await limiter.checkLimit(ip, 100, 60000) // 100 req/min 33 34 if (!allowed) { 35 return NextResponse.json({ 36 error: 'Rate limit exceeded' 37 }, { status: 429 }) 38 } 39 40 // Continue with request 41}

Background Jobs & Queues

Simple Queue Pattern

typescript
1class JobQueue<T> { 2 private queue: T[] = [] 3 private processing = false 4 5 async add(job: T): Promise<void> { 6 this.queue.push(job) 7 8 if (!this.processing) { 9 this.process() 10 } 11 } 12 13 private async process(): Promise<void> { 14 this.processing = true 15 16 while (this.queue.length > 0) { 17 const job = this.queue.shift()! 18 19 try { 20 await this.execute(job) 21 } catch (error) { 22 console.error('Job failed:', error) 23 } 24 } 25 26 this.processing = false 27 } 28 29 private async execute(job: T): Promise<void> { 30 // Job execution logic 31 } 32} 33 34// Usage for indexing markets 35interface IndexJob { 36 marketId: string 37} 38 39const indexQueue = new JobQueue<IndexJob>() 40 41export async function POST(request: Request) { 42 const { marketId } = await request.json() 43 44 // Add to queue instead of blocking 45 await indexQueue.add({ marketId }) 46 47 return NextResponse.json({ success: true, message: 'Job queued' }) 48}

Logging & Monitoring

Structured Logging

typescript
1interface LogContext { 2 userId?: string 3 requestId?: string 4 method?: string 5 path?: string 6 [key: string]: unknown 7} 8 9class Logger { 10 log(level: 'info' | 'warn' | 'error', message: string, context?: LogContext) { 11 const entry = { 12 timestamp: new Date().toISOString(), 13 level, 14 message, 15 ...context 16 } 17 18 console.log(JSON.stringify(entry)) 19 } 20 21 info(message: string, context?: LogContext) { 22 this.log('info', message, context) 23 } 24 25 warn(message: string, context?: LogContext) { 26 this.log('warn', message, context) 27 } 28 29 error(message: string, error: Error, context?: LogContext) { 30 this.log('error', message, { 31 ...context, 32 error: error.message, 33 stack: error.stack 34 }) 35 } 36} 37 38const logger = new Logger() 39 40// Usage 41export async function GET(request: Request) { 42 const requestId = crypto.randomUUID() 43 44 logger.info('Fetching markets', { 45 requestId, 46 method: 'GET', 47 path: '/api/markets' 48 }) 49 50 try { 51 const markets = await fetchMarkets() 52 return NextResponse.json({ success: true, data: markets }) 53 } catch (error) { 54 logger.error('Failed to fetch markets', error as Error, { requestId }) 55 return NextResponse.json({ error: 'Internal error' }, { status: 500 }) 56 } 57}

Remember: Backend patterns enable scalable, maintainable server-side applications. Choose patterns that fit your complexity level.

Related Skills

Looking for an alternative to backend-patterns or building a Categories.official AI Agent? Explore these related open-source MCP Servers.

View All

flags

Logo of facebook
facebook

flags is a feature flag management system that enables developers to check flag states, compare channels, and debug feature behavior differences across release channels.

243.6k
0
Design

extract-errors

Logo of facebook
facebook

extract-errors is a skill that assists in extracting and managing error codes in React applications using yarn extract-errors command.

243.6k
0
Design

fix

Logo of facebook
facebook

fix is a technical skill that resolves lint errors, formatting issues, and ensures code quality in declarative, frontend, and UI projects

243.6k
0
Design

flow

Logo of facebook
facebook

Flow is a type checking system for JavaScript, used to validate React code and ensure consistency across applications

243.6k
0
Design