[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M6D83B38X03VG4FAQBC4YRDN":3,"skill-same:01M6D83B38X03VG4FAQBC4YRDN":75},{"skillNo":4,"name":5,"nameZh":6,"description":7,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":16,"categories":17,"keywords":26,"publishedAt":46,"linkOnly":47,"markdownContent":48,"markdownBody":49,"frontMatter":50,"refName":52,"commitSha":53,"skillDirectory":54,"forksCount":55,"repositoryHtmlUrl":56,"repositoryHomepageUrl":6,"ownerHtmlUrl":57,"ownerBlogUrl":58,"ownerDescription":59,"updatedAt":60,"install":61,"resources":74},"01M6D83B38X03VG4FAQBC4YRDN","backend-patterns",null,"Backend architecture patterns, API design, database optimization, and server-side best practices for Node.js, Express, and Next.js API routes.","oabdelmaksoud\u002FSuperClaw","oabdelmaksoud","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F50699149?v=4","01M6D5CVVN778ZCDP1WHS816SP","Omar Abdelmaksoud","01M6D5CW1RHNSKCJR85GJACBFT",2,"MIT","https:\u002F\u002Fgithub.com\u002Foabdelmaksoud\u002FSuperClaw\u002Fblob\u002Fmain\u002Fupstream-sync\u002Fwork\u002Fecc\u002Fskills\u002Fbackend-patterns\u002FSKILL.md",[18,23],{"categoryNo":19,"categoryName":20,"taxonomyType":21,"taxonomyTypeDesc":22},"01JBSEEDCAT000000000000010","后端与接口","SCENARIO","使用场景",{"categoryNo":24,"categoryName":25,"taxonomyType":21,"taxonomyTypeDesc":22},"01JBSEEDCAT000000000000015","视觉设计",[27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45],"patterns","backend","backend patterns","Next.js","server-side","express","next","database optimization","node","js","design","api","architecture patterns","Optimization","server","database","best practices","api design","architecture","2026-11-10 10:12:30",false,"---\nname: backend-patterns\ndescription: Backend architecture patterns, API design, database optimization, and server-side best practices for Node.js, Express, and Next.js API routes.\norigin: ECC\n---\n\n# Backend Development Patterns\n\nBackend architecture patterns and best practices for scalable server-side applications.\n\n## When to Activate\n\n- Designing REST or GraphQL API endpoints\n- Implementing repository, service, or controller layers\n- Optimizing database queries (N+1, indexing, connection pooling)\n- Adding caching (Redis, in-memory, HTTP cache headers)\n- Setting up background jobs or async processing\n- Structuring error handling and validation for APIs\n- Building middleware (auth, logging, rate limiting)\n\n## API Design Patterns\n\n### RESTful API Structure\n\n```typescript\n\u002F\u002F ✅ Resource-based URLs\nGET    \u002Fapi\u002Fmarkets                 # List resources\nGET    \u002Fapi\u002Fmarkets\u002F:id             # Get single resource\nPOST   \u002Fapi\u002Fmarkets                 # Create resource\nPUT    \u002Fapi\u002Fmarkets\u002F:id             # Replace resource\nPATCH  \u002Fapi\u002Fmarkets\u002F:id             # Update resource\nDELETE \u002Fapi\u002Fmarkets\u002F:id             # Delete resource\n\n\u002F\u002F ✅ Query parameters for filtering, sorting, pagination\nGET \u002Fapi\u002Fmarkets?status=active&sort=volume&limit=20&offset=0\n```\n\n### Repository Pattern\n\n```typescript\n\u002F\u002F Abstract data access logic\ninterface MarketRepository {\n  findAll(filters?: MarketFilters): Promise\u003CMarket[]>\n  findById(id: string): Promise\u003CMarket | null>\n  create(data: CreateMarketDto): Promise\u003CMarket>\n  update(id: string, data: UpdateMarketDto): Promise\u003CMarket>\n  delete(id: string): Promise\u003Cvoid>\n}\n\nclass SupabaseMarketRepository implements MarketRepository {\n  async findAll(filters?: MarketFilters): Promise\u003CMarket[]> {\n    let query = supabase.from('markets').select('*')\n\n    if (filters?.status) {\n      query = query.eq('status', filters.status)\n    }\n\n    if (filters?.limit) {\n      query = query.limit(filters.limit)\n    }\n\n    const { data, error } = await query\n\n    if (error) throw new Error(error.message)\n    return data\n  }\n\n  \u002F\u002F Other methods...\n}\n```\n\n### Service Layer Pattern\n\n```typescript\n\u002F\u002F Business logic separated from data access\nclass MarketService {\n  constructor(private marketRepo: MarketRepository) {}\n\n  async searchMarkets(query: string, limit: number = 10): Promise\u003CMarket[]> {\n    \u002F\u002F Business logic\n    const embedding = await generateEmbedding(query)\n    const results = await this.vectorSearch(embedding, limit)\n\n    \u002F\u002F Fetch full data\n    const markets = await this.marketRepo.findByIds(results.map(r => r.id))\n\n    \u002F\u002F Sort by similarity\n    return markets.sort((a, b) => {\n      const scoreA = results.find(r => r.id === a.id)?.score || 0\n      const scoreB = results.find(r => r.id === b.id)?.score || 0\n      return scoreA - scoreB\n    })\n  }\n\n  private async vectorSearch(embedding: number[], limit: number) {\n    \u002F\u002F Vector search implementation\n  }\n}\n```\n\n### Middleware Pattern\n\n```typescript\n\u002F\u002F Request\u002Fresponse processing pipeline\nexport function withAuth(handler: NextApiHandler): NextApiHandler {\n  return async (req, res) => {\n    const token = req.headers.authorization?.replace('Bearer ', '')\n\n    if (!token) {\n      return res.status(401).json({ error: 'Unauthorized' })\n    }\n\n    try {\n      const user = await verifyToken(token)\n      req.user = user\n      return handler(req, res)\n    } catch (error) {\n      return res.status(401).json({ error: 'Invalid token' })\n    }\n  }\n}\n\n\u002F\u002F Usage\nexport default withAuth(async (req, res) => {\n  \u002F\u002F Handler has access to req.user\n})\n```\n\n## Database Patterns\n\n### Query Optimization\n\n```typescript\n\u002F\u002F ✅ GOOD: Select only needed columns\nconst { data } = await supabase\n  .from('markets')\n  .select('id, name, status, volume')\n  .eq('status', 'active')\n  .order('volume', { ascending: false })\n  .limit(10)\n\n\u002F\u002F ❌ BAD: Select everything\nconst { data } = await supabase\n  .from('markets')\n  .select('*')\n```\n\n### N+1 Query Prevention\n\n```typescript\n\u002F\u002F ❌ BAD: N+1 query problem\nconst markets = await getMarkets()\nfor (const market of markets) {\n  market.creator = await getUser(market.creator_id)  \u002F\u002F N queries\n}\n\n\u002F\u002F ✅ GOOD: Batch fetch\nconst markets = await getMarkets()\nconst creatorIds = markets.map(m => m.creator_id)\nconst creators = await getUsers(creatorIds)  \u002F\u002F 1 query\nconst creatorMap = new Map(creators.map(c => [c.id, c]))\n\nmarkets.forEach(market => {\n  market.creator = creatorMap.get(market.creator_id)\n})\n```\n\n### Transaction Pattern\n\n```typescript\nasync function createMarketWithPosition(\n  marketData: CreateMarketDto,\n  positionData: CreatePositionDto\n) {\n  \u002F\u002F Use Supabase transaction\n  const { data, error } = await supabase.rpc('create_market_with_position', {\n    market_data: marketData,\n    position_data: positionData\n  })\n\n  if (error) throw new Error('Transaction failed')\n  return data\n}\n\n\u002F\u002F SQL function in Supabase\nCREATE OR REPLACE FUNCTION create_market_with_position(\n  market_data jsonb,\n  position_data jsonb\n)\nRETURNS jsonb\nLANGUAGE plpgsql\nAS $$\nBEGIN\n  -- Start transaction automatically\n  INSERT INTO markets VALUES (market_data);\n  INSERT INTO positions VALUES (position_data);\n  RETURN jsonb_build_object('success', true);\nEXCEPTION\n  WHEN OTHERS THEN\n    -- Rollback happens automatically\n    RETURN jsonb_build_object('success', false, 'error', SQLERRM);\nEND;\n$$;\n```\n\n## Caching Strategies\n\n### Redis Caching Layer\n\n```typescript\nclass CachedMarketRepository implements MarketRepository {\n  constructor(\n    private baseRepo: MarketRepository,\n    private redis: RedisClient\n  ) {}\n\n  async findById(id: string): Promise\u003CMarket | null> {\n    \u002F\u002F Check cache first\n    const cached = await this.redis.get(`market:${id}`)\n\n    if (cached) {\n      return JSON.parse(cached)\n    }\n\n    \u002F\u002F Cache miss - fetch from database\n    const market = await this.baseRepo.findById(id)\n\n    if (market) {\n      \u002F\u002F Cache for 5 minutes\n      await this.redis.setex(`market:${id}`, 300, JSON.stringify(market))\n    }\n\n    return market\n  }\n\n  async invalidateCache(id: string): Promise\u003Cvoid> {\n    await this.redis.del(`market:${id}`)\n  }\n}\n```\n\n### Cache-Aside Pattern\n\n```typescript\nasync function getMarketWithCache(id: string): Promise\u003CMarket> {\n  const cacheKey = `market:${id}`\n\n  \u002F\u002F Try cache\n  const cached = await redis.get(cacheKey)\n  if (cached) return JSON.parse(cached)\n\n  \u002F\u002F Cache miss - fetch from DB\n  const market = await db.markets.findUnique({ where: { id } })\n\n  if (!market) throw new Error('Market not found')\n\n  \u002F\u002F Update cache\n  await redis.setex(cacheKey, 300, JSON.stringify(market))\n\n  return market\n}\n```\n\n## Error Handling Patterns\n\n### Centralized Error Handler\n\n```typescript\nclass ApiError extends Error {\n  constructor(\n    public statusCode: number,\n    public message: string,\n    public isOperational = true\n  ) {\n    super(message)\n    Object.setPrototypeOf(this, ApiError.prototype)\n  }\n}\n\nexport function errorHandler(error: unknown, req: Request): Response {\n  if (error instanceof ApiError) {\n    return NextResponse.json({\n      success: false,\n      error: error.message\n    }, { status: error.statusCode })\n  }\n\n  if (error instanceof z.ZodError) {\n    return NextResponse.json({\n      success: false,\n      error: 'Validation failed',\n      details: error.errors\n    }, { status: 400 })\n  }\n\n  \u002F\u002F Log unexpected errors\n  console.error('Unexpected error:', error)\n\n  return NextResponse.json({\n    success: false,\n    error: 'Internal server error'\n  }, { status: 500 })\n}\n\n\u002F\u002F Usage\nexport async function GET(request: Request) {\n  try {\n    const data = await fetchData()\n    return NextResponse.json({ success: true, data })\n  } catch (error) {\n    return errorHandler(error, request)\n  }\n}\n```\n\n### Retry with Exponential Backoff\n\n```typescript\nasync function fetchWithRetry\u003CT>(\n  fn: () => Promise\u003CT>,\n  maxRetries = 3\n): Promise\u003CT> {\n  let lastError: Error\n\n  for (let i = 0; i \u003C maxRetries; i++) {\n    try {\n      return await fn()\n    } catch (error) {\n      lastError = error as Error\n\n      if (i \u003C maxRetries - 1) {\n        \u002F\u002F Exponential backoff: 1s, 2s, 4s\n        const delay = Math.pow(2, i) * 1000\n        await new Promise(resolve => setTimeout(resolve, delay))\n      }\n    }\n  }\n\n  throw lastError!\n}\n\n\u002F\u002F Usage\nconst data = await fetchWithRetry(() => fetchFromAPI())\n```\n\n## Authentication & Authorization\n\n### JWT Token Validation\n\n```typescript\nimport jwt from 'jsonwebtoken'\n\ninterface JWTPayload {\n  userId: string\n  email: string\n  role: 'admin' | 'user'\n}\n\nexport function verifyToken(token: string): JWTPayload {\n  try {\n    const payload = jwt.verify(token, process.env.JWT_SECRET!) as JWTPayload\n    return payload\n  } catch (error) {\n    throw new ApiError(401, 'Invalid token')\n  }\n}\n\nexport async function requireAuth(request: Request) {\n  const token = request.headers.get('authorization')?.replace('Bearer ', '')\n\n  if (!token) {\n    throw new ApiError(401, 'Missing authorization token')\n  }\n\n  return verifyToken(token)\n}\n\n\u002F\u002F Usage in API route\nexport async function GET(request: Request) {\n  const user = await requireAuth(request)\n\n  const data = await getDataForUser(user.userId)\n\n  return NextResponse.json({ success: true, data })\n}\n```\n\n### Role-Based Access Control\n\n```typescript\ntype Permission = 'read' | 'write' | 'delete' | 'admin'\n\ninterface User {\n  id: string\n  role: 'admin' | 'moderator' | 'user'\n}\n\nconst rolePermissions: Record\u003CUser['role'], Permission[]> = {\n  admin: ['read', 'write', 'delete', 'admin'],\n  moderator: ['read', 'write', 'delete'],\n  user: ['read', 'write']\n}\n\nexport function hasPermission(user: User, permission: Permission): boolean {\n  return rolePermissions[user.role].includes(permission)\n}\n\nexport function requirePermission(permission: Permission) {\n  return (handler: (request: Request, user: User) => Promise\u003CResponse>) => {\n    return async (request: Request) => {\n      const user = await requireAuth(request)\n\n      if (!hasPermission(user, permission)) {\n        throw new ApiError(403, 'Insufficient permissions')\n      }\n\n      return handler(request, user)\n    }\n  }\n}\n\n\u002F\u002F Usage - HOF wraps the handler\nexport const DELETE = requirePermission('delete')(\n  async (request: Request, user: User) => {\n    \u002F\u002F Handler receives authenticated user with verified permission\n    return new Response('Deleted', { status: 200 })\n  }\n)\n```\n\n## Rate Limiting\n\n### Simple In-Memory Rate Limiter\n\n```typescript\nclass RateLimiter {\n  private requests = new Map\u003Cstring, number[]>()\n\n  async checkLimit(\n    identifier: string,\n    maxRequests: number,\n    windowMs: number\n  ): Promise\u003Cboolean> {\n    const now = Date.now()\n    const requests = this.requests.get(identifier) || []\n\n    \u002F\u002F Remove old requests outside window\n    const recentRequests = requests.filter(time => now - time \u003C windowMs)\n\n    if (recentRequests.length >= maxRequests) {\n      return false  \u002F\u002F Rate limit exceeded\n    }\n\n    \u002F\u002F Add current request\n    recentRequests.push(now)\n    this.requests.set(identifier, recentRequests)\n\n    return true\n  }\n}\n\nconst limiter = new RateLimiter()\n\nexport async function GET(request: Request) {\n  const ip = request.headers.get('x-forwarded-for') || 'unknown'\n\n  const allowed = await limiter.checkLimit(ip, 100, 60000)  \u002F\u002F 100 req\u002Fmin\n\n  if (!allowed) {\n    return NextResponse.json({\n      error: 'Rate limit exceeded'\n    }, { status: 429 })\n  }\n\n  \u002F\u002F Continue with request\n}\n```\n\n## Background Jobs & Queues\n\n### Simple Queue Pattern\n\n```typescript\nclass JobQueue\u003CT> {\n  private queue: T[] = []\n  private processing = false\n\n  async add(job: T): Promise\u003Cvoid> {\n    this.queue.push(job)\n\n    if (!this.processing) {\n      this.process()\n    }\n  }\n\n  private async process(): Promise\u003Cvoid> {\n    this.processing = true\n\n    while (this.queue.length > 0) {\n      const job = this.queue.shift()!\n\n      try {\n        await this.execute(job)\n      } catch (error) {\n        console.error('Job failed:', error)\n      }\n    }\n\n    this.processing = false\n  }\n\n  private async execute(job: T): Promise\u003Cvoid> {\n    \u002F\u002F Job execution logic\n  }\n}\n\n\u002F\u002F Usage for indexing markets\ninterface IndexJob {\n  marketId: string\n}\n\nconst indexQueue = new JobQueue\u003CIndexJob>()\n\nexport async function POST(request: Request) {\n  const { marketId } = await request.json()\n\n  \u002F\u002F Add to queue instead of blocking\n  await indexQueue.add({ marketId })\n\n  return NextResponse.json({ success: true, message: 'Job queued' })\n}\n```\n\n## Logging & Monitoring\n\n### Structured Logging\n\n```typescript\ninterface LogContext {\n  userId?: string\n  requestId?: string\n  method?: string\n  path?: string\n  [key: string]: unknown\n}\n\nclass Logger {\n  log(level: 'info' | 'warn' | 'error', message: string, context?: LogContext) {\n    const entry = {\n      timestamp: new Date().toISOString(),\n      level,\n      message,\n      ...context\n    }\n\n    console.log(JSON.stringify(entry))\n  }\n\n  info(message: string, context?: LogContext) {\n    this.log('info', message, context)\n  }\n\n  warn(message: string, context?: LogContext) {\n    this.log('warn', message, context)\n  }\n\n  error(message: string, error: Error, context?: LogContext) {\n    this.log('error', message, {\n      ...context,\n      error: error.message,\n      stack: error.stack\n    })\n  }\n}\n\nconst logger = new Logger()\n\n\u002F\u002F Usage\nexport async function GET(request: Request) {\n  const requestId = crypto.randomUUID()\n\n  logger.info('Fetching markets', {\n    requestId,\n    method: 'GET',\n    path: '\u002Fapi\u002Fmarkets'\n  })\n\n  try {\n    const markets = await fetchMarkets()\n    return NextResponse.json({ success: true, data: markets })\n  } catch (error) {\n    logger.error('Failed to fetch markets', error as Error, { requestId })\n    return NextResponse.json({ error: 'Internal error' }, { status: 500 })\n  }\n}\n```\n\n**Remember**: Backend patterns enable scalable, maintainable server-side applications. Choose patterns that fit your complexity level.\n","# Backend Development Patterns\n\nBackend architecture patterns and best practices for scalable server-side applications.\n\n## When to Activate\n\n- Designing REST or GraphQL API endpoints\n- Implementing repository, service, or controller layers\n- Optimizing database queries (N+1, indexing, connection pooling)\n- Adding caching (Redis, in-memory, HTTP cache headers)\n- Setting up background jobs or async processing\n- Structuring error handling and validation for APIs\n- Building middleware (auth, logging, rate limiting)\n\n## API Design Patterns\n\n### RESTful API Structure\n\n```typescript\n\u002F\u002F ✅ Resource-based URLs\nGET    \u002Fapi\u002Fmarkets                 # List resources\nGET    \u002Fapi\u002Fmarkets\u002F:id             # Get single resource\nPOST   \u002Fapi\u002Fmarkets                 # Create resource\nPUT    \u002Fapi\u002Fmarkets\u002F:id             # Replace resource\nPATCH  \u002Fapi\u002Fmarkets\u002F:id             # Update resource\nDELETE \u002Fapi\u002Fmarkets\u002F:id             # Delete resource\n\n\u002F\u002F ✅ Query parameters for filtering, sorting, pagination\nGET \u002Fapi\u002Fmarkets?status=active&sort=volume&limit=20&offset=0\n```\n\n### Repository Pattern\n\n```typescript\n\u002F\u002F Abstract data access logic\ninterface MarketRepository {\n  findAll(filters?: MarketFilters): Promise\u003CMarket[]>\n  findById(id: string): Promise\u003CMarket | null>\n  create(data: CreateMarketDto): Promise\u003CMarket>\n  update(id: string, data: UpdateMarketDto): Promise\u003CMarket>\n  delete(id: string): Promise\u003Cvoid>\n}\n\nclass SupabaseMarketRepository implements MarketRepository {\n  async findAll(filters?: MarketFilters): Promise\u003CMarket[]> {\n    let query = supabase.from('markets').select('*')\n\n    if (filters?.status) {\n      query = query.eq('status', filters.status)\n    }\n\n    if (filters?.limit) {\n      query = query.limit(filters.limit)\n    }\n\n    const { data, error } = await query\n\n    if (error) throw new Error(error.message)\n    return data\n  }\n\n  \u002F\u002F Other methods...\n}\n```\n\n### Service Layer Pattern\n\n```typescript\n\u002F\u002F Business logic separated from data access\nclass MarketService {\n  constructor(private marketRepo: MarketRepository) {}\n\n  async searchMarkets(query: string, limit: number = 10): Promise\u003CMarket[]> {\n    \u002F\u002F Business logic\n    const embedding = await generateEmbedding(query)\n    const results = await this.vectorSearch(embedding, limit)\n\n    \u002F\u002F Fetch full data\n    const markets = await this.marketRepo.findByIds(results.map(r => r.id))\n\n    \u002F\u002F Sort by similarity\n    return markets.sort((a, b) => {\n      const scoreA = results.find(r => r.id === a.id)?.score || 0\n      const scoreB = results.find(r => r.id === b.id)?.score || 0\n      return scoreA - scoreB\n    })\n  }\n\n  private async vectorSearch(embedding: number[], limit: number) {\n    \u002F\u002F Vector search implementation\n  }\n}\n```\n\n### Middleware Pattern\n\n```typescript\n\u002F\u002F Request\u002Fresponse processing pipeline\nexport function withAuth(handler: NextApiHandler): NextApiHandler {\n  return async (req, res) => {\n    const token = req.headers.authorization?.replace('Bearer ', '')\n\n    if (!token) {\n      return res.status(401).json({ error: 'Unauthorized' })\n    }\n\n    try {\n      const user = await verifyToken(token)\n      req.user = user\n      return handler(req, res)\n    } catch (error) {\n      return res.status(401).json({ error: 'Invalid token' })\n    }\n  }\n}\n\n\u002F\u002F Usage\nexport default withAuth(async (req, res) => {\n  \u002F\u002F Handler has access to req.user\n})\n```\n\n## Database Patterns\n\n### Query Optimization\n\n```typescript\n\u002F\u002F ✅ GOOD: Select only needed columns\nconst { data } = await supabase\n  .from('markets')\n  .select('id, name, status, volume')\n  .eq('status', 'active')\n  .order('volume', { ascending: false })\n  .limit(10)\n\n\u002F\u002F ❌ BAD: Select everything\nconst { data } = await supabase\n  .from('markets')\n  .select('*')\n```\n\n### N+1 Query Prevention\n\n```typescript\n\u002F\u002F ❌ BAD: N+1 query problem\nconst markets = await getMarkets()\nfor (const market of markets) {\n  market.creator = await getUser(market.creator_id)  \u002F\u002F N queries\n}\n\n\u002F\u002F ✅ GOOD: Batch fetch\nconst markets = await getMarkets()\nconst creatorIds = markets.map(m => m.creator_id)\nconst creators = await getUsers(creatorIds)  \u002F\u002F 1 query\nconst creatorMap = new Map(creators.map(c => [c.id, c]))\n\nmarkets.forEach(market => {\n  market.creator = creatorMap.get(market.creator_id)\n})\n```\n\n### Transaction Pattern\n\n```typescript\nasync function createMarketWithPosition(\n  marketData: CreateMarketDto,\n  positionData: CreatePositionDto\n) {\n  \u002F\u002F Use Supabase transaction\n  const { data, error } = await supabase.rpc('create_market_with_position', {\n    market_data: marketData,\n    position_data: positionData\n  })\n\n  if (error) throw new Error('Transaction failed')\n  return data\n}\n\n\u002F\u002F SQL function in Supabase\nCREATE OR REPLACE FUNCTION create_market_with_position(\n  market_data jsonb,\n  position_data jsonb\n)\nRETURNS jsonb\nLANGUAGE plpgsql\nAS $$\nBEGIN\n  -- Start transaction automatically\n  INSERT INTO markets VALUES (market_data);\n  INSERT INTO positions VALUES (position_data);\n  RETURN jsonb_build_object('success', true);\nEXCEPTION\n  WHEN OTHERS THEN\n    -- Rollback happens automatically\n    RETURN jsonb_build_object('success', false, 'error', SQLERRM);\nEND;\n$$;\n```\n\n## Caching Strategies\n\n### Redis Caching Layer\n\n```typescript\nclass CachedMarketRepository implements MarketRepository {\n  constructor(\n    private baseRepo: MarketRepository,\n    private redis: RedisClient\n  ) {}\n\n  async findById(id: string): Promise\u003CMarket | null> {\n    \u002F\u002F Check cache first\n    const cached = await this.redis.get(`market:${id}`)\n\n    if (cached) {\n      return JSON.parse(cached)\n    }\n\n    \u002F\u002F Cache miss - fetch from database\n    const market = await this.baseRepo.findById(id)\n\n    if (market) {\n      \u002F\u002F Cache for 5 minutes\n      await this.redis.setex(`market:${id}`, 300, JSON.stringify(market))\n    }\n\n    return market\n  }\n\n  async invalidateCache(id: string): Promise\u003Cvoid> {\n    await this.redis.del(`market:${id}`)\n  }\n}\n```\n\n### Cache-Aside Pattern\n\n```typescript\nasync function getMarketWithCache(id: string): Promise\u003CMarket> {\n  const cacheKey = `market:${id}`\n\n  \u002F\u002F Try cache\n  const cached = await redis.get(cacheKey)\n  if (cached) return JSON.parse(cached)\n\n  \u002F\u002F Cache miss - fetch from DB\n  const market = await db.markets.findUnique({ where: { id } })\n\n  if (!market) throw new Error('Market not found')\n\n  \u002F\u002F Update cache\n  await redis.setex(cacheKey, 300, JSON.stringify(market))\n\n  return market\n}\n```\n\n## Error Handling Patterns\n\n### Centralized Error Handler\n\n```typescript\nclass ApiError extends Error {\n  constructor(\n    public statusCode: number,\n    public message: string,\n    public isOperational = true\n  ) {\n    super(message)\n    Object.setPrototypeOf(this, ApiError.prototype)\n  }\n}\n\nexport function errorHandler(error: unknown, req: Request): Response {\n  if (error instanceof ApiError) {\n    return NextResponse.json({\n      success: false,\n      error: error.message\n    }, { status: error.statusCode })\n  }\n\n  if (error instanceof z.ZodError) {\n    return NextResponse.json({\n      success: false,\n      error: 'Validation failed',\n      details: error.errors\n    }, { status: 400 })\n  }\n\n  \u002F\u002F Log unexpected errors\n  console.error('Unexpected error:', error)\n\n  return NextResponse.json({\n    success: false,\n    error: 'Internal server error'\n  }, { status: 500 })\n}\n\n\u002F\u002F Usage\nexport async function GET(request: Request) {\n  try {\n    const data = await fetchData()\n    return NextResponse.json({ success: true, data })\n  } catch (error) {\n    return errorHandler(error, request)\n  }\n}\n```\n\n### Retry with Exponential Backoff\n\n```typescript\nasync function fetchWithRetry\u003CT>(\n  fn: () => Promise\u003CT>,\n  maxRetries = 3\n): Promise\u003CT> {\n  let lastError: Error\n\n  for (let i = 0; i \u003C maxRetries; i++) {\n    try {\n      return await fn()\n    } catch (error) {\n      lastError = error as Error\n\n      if (i \u003C maxRetries - 1) {\n        \u002F\u002F Exponential backoff: 1s, 2s, 4s\n        const delay = Math.pow(2, i) * 1000\n        await new Promise(resolve => setTimeout(resolve, delay))\n      }\n    }\n  }\n\n  throw lastError!\n}\n\n\u002F\u002F Usage\nconst data = await fetchWithRetry(() => fetchFromAPI())\n```\n\n## Authentication & Authorization\n\n### JWT Token Validation\n\n```typescript\nimport jwt from 'jsonwebtoken'\n\ninterface JWTPayload {\n  userId: string\n  email: string\n  role: 'admin' | 'user'\n}\n\nexport function verifyToken(token: string): JWTPayload {\n  try {\n    const payload = jwt.verify(token, process.env.JWT_SECRET!) as JWTPayload\n    return payload\n  } catch (error) {\n    throw new ApiError(401, 'Invalid token')\n  }\n}\n\nexport async function requireAuth(request: Request) {\n  const token = request.headers.get('authorization')?.replace('Bearer ', '')\n\n  if (!token) {\n    throw new ApiError(401, 'Missing authorization token')\n  }\n\n  return verifyToken(token)\n}\n\n\u002F\u002F Usage in API route\nexport async function GET(request: Request) {\n  const user = await requireAuth(request)\n\n  const data = await getDataForUser(user.userId)\n\n  return NextResponse.json({ success: true, data })\n}\n```\n\n### Role-Based Access Control\n\n```typescript\ntype Permission = 'read' | 'write' | 'delete' | 'admin'\n\ninterface User {\n  id: string\n  role: 'admin' | 'moderator' | 'user'\n}\n\nconst rolePermissions: Record\u003CUser['role'], Permission[]> = {\n  admin: ['read', 'write', 'delete', 'admin'],\n  moderator: ['read', 'write', 'delete'],\n  user: ['read', 'write']\n}\n\nexport function hasPermission(user: User, permission: Permission): boolean {\n  return rolePermissions[user.role].includes(permission)\n}\n\nexport function requirePermission(permission: Permission) {\n  return (handler: (request: Request, user: User) => Promise\u003CResponse>) => {\n    return async (request: Request) => {\n      const user = await requireAuth(request)\n\n      if (!hasPermission(user, permission)) {\n        throw new ApiError(403, 'Insufficient permissions')\n      }\n\n      return handler(request, user)\n    }\n  }\n}\n\n\u002F\u002F Usage - HOF wraps the handler\nexport const DELETE = requirePermission('delete')(\n  async (request: Request, user: User) => {\n    \u002F\u002F Handler receives authenticated user with verified permission\n    return new Response('Deleted', { status: 200 })\n  }\n)\n```\n\n## Rate Limiting\n\n### Simple In-Memory Rate Limiter\n\n```typescript\nclass RateLimiter {\n  private requests = new Map\u003Cstring, number[]>()\n\n  async checkLimit(\n    identifier: string,\n    maxRequests: number,\n    windowMs: number\n  ): Promise\u003Cboolean> {\n    const now = Date.now()\n    const requests = this.requests.get(identifier) || []\n\n    \u002F\u002F Remove old requests outside window\n    const recentRequests = requests.filter(time => now - time \u003C windowMs)\n\n    if (recentRequests.length >= maxRequests) {\n      return false  \u002F\u002F Rate limit exceeded\n    }\n\n    \u002F\u002F Add current request\n    recentRequests.push(now)\n    this.requests.set(identifier, recentRequests)\n\n    return true\n  }\n}\n\nconst limiter = new RateLimiter()\n\nexport async function GET(request: Request) {\n  const ip = request.headers.get('x-forwarded-for') || 'unknown'\n\n  const allowed = await limiter.checkLimit(ip, 100, 60000)  \u002F\u002F 100 req\u002Fmin\n\n  if (!allowed) {\n    return NextResponse.json({\n      error: 'Rate limit exceeded'\n    }, { status: 429 })\n  }\n\n  \u002F\u002F Continue with request\n}\n```\n\n## Background Jobs & Queues\n\n### Simple Queue Pattern\n\n```typescript\nclass JobQueue\u003CT> {\n  private queue: T[] = []\n  private processing = false\n\n  async add(job: T): Promise\u003Cvoid> {\n    this.queue.push(job)\n\n    if (!this.processing) {\n      this.process()\n    }\n  }\n\n  private async process(): Promise\u003Cvoid> {\n    this.processing = true\n\n    while (this.queue.length > 0) {\n      const job = this.queue.shift()!\n\n      try {\n        await this.execute(job)\n      } catch (error) {\n        console.error('Job failed:', error)\n      }\n    }\n\n    this.processing = false\n  }\n\n  private async execute(job: T): Promise\u003Cvoid> {\n    \u002F\u002F Job execution logic\n  }\n}\n\n\u002F\u002F Usage for indexing markets\ninterface IndexJob {\n  marketId: string\n}\n\nconst indexQueue = new JobQueue\u003CIndexJob>()\n\nexport async function POST(request: Request) {\n  const { marketId } = await request.json()\n\n  \u002F\u002F Add to queue instead of blocking\n  await indexQueue.add({ marketId })\n\n  return NextResponse.json({ success: true, message: 'Job queued' })\n}\n```\n\n## Logging & Monitoring\n\n### Structured Logging\n\n```typescript\ninterface LogContext {\n  userId?: string\n  requestId?: string\n  method?: string\n  path?: string\n  [key: string]: unknown\n}\n\nclass Logger {\n  log(level: 'info' | 'warn' | 'error', message: string, context?: LogContext) {\n    const entry = {\n      timestamp: new Date().toISOString(),\n      level,\n      message,\n      ...context\n    }\n\n    console.log(JSON.stringify(entry))\n  }\n\n  info(message: string, context?: LogContext) {\n    this.log('info', message, context)\n  }\n\n  warn(message: string, context?: LogContext) {\n    this.log('warn', message, context)\n  }\n\n  error(message: string, error: Error, context?: LogContext) {\n    this.log('error', message, {\n      ...context,\n      error: error.message,\n      stack: error.stack\n    })\n  }\n}\n\nconst logger = new Logger()\n\n\u002F\u002F Usage\nexport async function GET(request: Request) {\n  const requestId = crypto.randomUUID()\n\n  logger.info('Fetching markets', {\n    requestId,\n    method: 'GET',\n    path: '\u002Fapi\u002Fmarkets'\n  })\n\n  try {\n    const markets = await fetchMarkets()\n    return NextResponse.json({ success: true, data: markets })\n  } catch (error) {\n    logger.error('Failed to fetch markets', error as Error, { requestId })\n    return NextResponse.json({ error: 'Internal error' }, { status: 500 })\n  }\n}\n```\n\n**Remember**: Backend patterns enable scalable, maintainable server-side applications. Choose patterns that fit your complexity level.\n",{"name":5,"origin":51,"description":7},"ECC","main","7b610356e36623652299fa2acb477ff821b1d920","upstream-sync\u002Fwork\u002Fecc\u002Fskills\u002Fbackend-patterns",0,"https:\u002F\u002Fgithub.com\u002Foabdelmaksoud\u002FSuperClaw","https:\u002F\u002Fgithub.com\u002Foabdelmaksoud","https:\u002F\u002Fwww.linkedin.com\u002Fin\u002Fo-abdelmaksoud\u002F","Full-Stack Engineer | AI Systems Architect | Building autonomous multi-agent systems","2026-03-08 21:12:53",{"source":8,"skillName":5,"commands":62,"prompt":72,"zipAvailable":73},[63,66,69],{"tool":64,"command":65},"npx","npx skills add oabdelmaksoud\u002FSuperClaw --skill backend-patterns",{"tool":67,"command":68},"bunx","bunx skills add oabdelmaksoud\u002FSuperClaw --skill backend-patterns",{"tool":70,"command":71},"pnpm","pnpm dlx skills add oabdelmaksoud\u002FSuperClaw --skill backend-patterns","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002Foabdelmaksoud\u002FSuperClaw\u002Fblob\u002Fmain\u002Fupstream-sync\u002Fwork\u002Fecc\u002Fskills\u002Fbackend-patterns\u002FSKILL.md",true,[],[76,95,109,140,161,180],{"skillNo":77,"name":78,"nameZh":6,"description":79,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":80,"categories":81,"keywords":85,"publishedAt":46},"01M6D88QCPTBZVCRED0NZ1Y8K8","visa-doc-translate","Translate visa application documents (images) to English and create a bilingual PDF with original and translation","https:\u002F\u002Fgithub.com\u002Foabdelmaksoud\u002FSuperClaw\u002Fblob\u002Fmain\u002Fupstream-sync\u002Fwork\u002Fecc\u002Fskills\u002Fvisa-doc-translate\u002FSKILL.md",[82],{"categoryNo":83,"categoryName":84,"taxonomyType":21,"taxonomyTypeDesc":22},"01JBSEEDCAT000000000000002","文档处理",[86,87,88,89,90,91,92,93,94],"translate","doc","visa doc translate","translation","application","create","images","PDF","documents",{"skillNo":96,"name":97,"nameZh":6,"description":98,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":99,"categories":100,"keywords":101,"publishedAt":46},"01M6D88NBM95T3TFM50CYYAP65","verification-loop","A comprehensive verification system for Claude Code sessions.","https:\u002F\u002Fgithub.com\u002Foabdelmaksoud\u002FSuperClaw\u002Fblob\u002Fmain\u002Fupstream-sync\u002Fwork\u002Fecc\u002Fskills\u002Fverification-loop\u002FSKILL.md",[],[102,103,104,105,106,107,108],"verification","loop","verification loop","sessions","code","claude code sessions","system",{"skillNo":110,"name":111,"nameZh":6,"description":112,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":113,"categories":114,"keywords":126,"publishedAt":46},"01M6D88JFZ2P996GVRHJNSZSTM","tdd-workflow","Use this skill when writing new features, fixing bugs, or refactoring code. Enforces test-driven development with 80%+ coverage including unit, integration, and E2E tests.","https:\u002F\u002Fgithub.com\u002Foabdelmaksoud\u002FSuperClaw\u002Fblob\u002Fmain\u002Fupstream-sync\u002Fwork\u002Fecc\u002Fskills\u002Ftdd-workflow\u002FSKILL.md",[115,118,121],{"categoryNo":116,"categoryName":117,"taxonomyType":21,"taxonomyTypeDesc":22},"01JBSEEDCAT000000000000008","测试与质量",{"categoryNo":119,"categoryName":120,"taxonomyType":21,"taxonomyTypeDesc":22},"01JBSEEDCAT000000000000023","Skill与智能体开发",{"categoryNo":122,"categoryName":123,"taxonomyType":124,"taxonomyTypeDesc":125},"01JBSEEDCAT000000000000030","开发工程师","PROFESSION","适用职业",[127,128,129,130,131,132,106,133,134,135,136,137,138,139],"tdd","workflow","tdd workflow","e2e tests","e2e","integration","development","use","test","refactoring","coverage","tests","writing",{"skillNo":141,"name":142,"nameZh":6,"description":143,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":144,"categories":145,"keywords":146,"publishedAt":46},"01M6D88FTHRRSVJMXF2G7MQAK3","swiftui-patterns","SwiftUI architecture patterns, state management with @Observable, view composition, navigation, performance optimization, and modern iOS\u002FmacOS UI best practices.","https:\u002F\u002Fgithub.com\u002Foabdelmaksoud\u002FSuperClaw\u002Fblob\u002Fmain\u002Fupstream-sync\u002Fwork\u002Fecc\u002Fskills\u002Fswiftui-patterns\u002FSKILL.md",[],[27,147,148,45,149,150,151,43,152,153,40,154,39,155,156,157,158,159,160],"swiftui","swiftui patterns","macos","performance","state management","state","ui","ios","Composition","performance optimization","view","management","swiftui architecture","navigation",{"skillNo":162,"name":163,"nameZh":6,"description":164,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":165,"categories":166,"keywords":168,"publishedAt":46},"01M6D88D527QTQT9DKHTRFN6EA","swift-protocol-di-testing","Protocol-based dependency injection for testable Swift code — mock file system, network, and external APIs using focused protocols and Swift Testing.","https:\u002F\u002Fgithub.com\u002Foabdelmaksoud\u002FSuperClaw\u002Fblob\u002Fmain\u002Fupstream-sync\u002Fwork\u002Fecc\u002Fskills\u002Fswift-protocol-di-testing\u002FSKILL.md",[167],{"categoryNo":116,"categoryName":117,"taxonomyType":21,"taxonomyTypeDesc":22},[169,170,171,172,106,173,174,175,176,108,177,178,179],"swift protocol di testing","protocol","swift","testing","protocols","file","network","injection","dependency","swift testing","dependency injection",{"skillNo":181,"name":182,"nameZh":6,"description":183,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":184,"categories":185,"keywords":186,"publishedAt":46},"01M6D88AJW8H2QNWSW5ZY82R43","swift-concurrency-6-2","Swift 6.2 Approachable Concurrency — single-threaded by default, @concurrent for explicit background offloading, isolated conformances for main actor types.","https:\u002F\u002Fgithub.com\u002Foabdelmaksoud\u002FSuperClaw\u002Fblob\u002Fmain\u002Fupstream-sync\u002Fwork\u002Fecc\u002Fskills\u002Fswift-concurrency-6-2\u002FSKILL.md",[],[187,188,171,189,190,52],"concurrency","swift concurrency","swift concurrency 6 2","default"]