[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M72ZQWHV6PRFPDFBEXKHYRWX":3,"skill-same:01M72ZQWHV6PRFPDFBEXKHYRWX":48},{"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":18,"publishedAt":19,"linkOnly":20,"markdownContent":21,"markdownBody":22,"frontMatter":23,"refName":25,"commitSha":26,"skillDirectory":27,"forksCount":28,"repositoryHtmlUrl":29,"repositoryHomepageUrl":6,"ownerHtmlUrl":30,"ownerBlogUrl":31,"ownerDescription":32,"updatedAt":33,"install":34,"resources":47},"01M72ZQWHV6PRFPDFBEXKHYRWX","backend-patterns",null,"Node.js, Express ve Next.js API routes için backend mimari kalıpları, API tasarımı, veritabanı optimizasyonu ve sunucu tarafı en iyi uygulamalar.","SriramGandhiS\u002FSkills","SriramGandhiS","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F211849986?v=4","01M72WQCW12BYX71C6WN584TTA","Sriram S","01M72WQCWTJ2RD0ET1X31AF1RC",1,"MIT","https:\u002F\u002Fgithub.com\u002FSriramGandhiS\u002FSkills\u002Fblob\u002Fmaster\u002Fskills\u002Feverything-claude-code\u002Fdocs\u002Ftr\u002Fskills\u002Fbackend-patterns\u002FSKILL.md",[],[],"2026-11-11 15:11:14",false,"---\nname: backend-patterns\ndescription: Node.js, Express ve Next.js API routes için backend mimari kalıpları, API tasarımı, veritabanı optimizasyonu ve sunucu tarafı en iyi uygulamalar.\norigin: ECC\n---\n\n# Backend Geliştirme Kalıpları\n\nÖlçeklenebilir sunucu tarafı uygulamalar için backend mimari kalıpları ve en iyi uygulamalar.\n\n## Ne Zaman Aktifleştirmelisiniz\n\n- REST veya GraphQL API endpoint'leri tasarlarken\n- Repository, service veya controller katmanları uygularken\n- Veritabanı sorgularını optimize ederken (N+1, indeksleme, bağlantı havuzu)\n- Önbellekleme eklerken (Redis, in-memory, HTTP cache başlıkları)\n- Arka plan işleri veya async işleme ayarlarken\n- API'ler için hata yönetimi ve doğrulama yapılandırırken\n- Middleware oluştururken (auth, logging, rate limiting)\n\n## API Tasarım Kalıpları\n\n### RESTful API Yapısı\n\n```typescript\n\u002F\u002F PASS: Kaynak tabanlı URL'ler\nGET    \u002Fapi\u002Fmarkets                 # Kaynakları listele\nGET    \u002Fapi\u002Fmarkets\u002F:id             # Tek kaynak getir\nPOST   \u002Fapi\u002Fmarkets                 # Kaynak oluştur\nPUT    \u002Fapi\u002Fmarkets\u002F:id             # Kaynağı değiştir (tam)\nPATCH  \u002Fapi\u002Fmarkets\u002F:id             # Kaynağı güncelle (kısmi)\nDELETE \u002Fapi\u002Fmarkets\u002F:id             # Kaynağı sil\n\n\u002F\u002F PASS: Filtreleme, sıralama, sayfalama için query parametreleri\nGET \u002Fapi\u002Fmarkets?status=active&sort=volume&limit=20&offset=0\n```\n\n### Repository Kalıbı\n\n```typescript\n\u002F\u002F Veri erişim mantığını soyutla\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 Diğer metodlar...\n}\n```\n\n### Service Katmanı Kalıbı\n\n```typescript\n\u002F\u002F İş mantığı veri erişiminden ayrılmış\nclass MarketService {\n  constructor(private marketRepo: MarketRepository) {}\n\n  async searchMarkets(query: string, limit: number = 10): Promise\u003CMarket[]> {\n    \u002F\u002F İş mantığı\n    const embedding = await generateEmbedding(query)\n    const results = await this.vectorSearch(embedding, limit)\n\n    \u002F\u002F Tam veriyi getir\n    const markets = await this.marketRepo.findByIds(results.map(r => r.id))\n\n    \u002F\u002F Benzerliğe göre sırala\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 arama implementasyonu\n  }\n}\n```\n\n### Middleware Kalıbı\n\n```typescript\n\u002F\u002F Request\u002Fresponse işleme hattı\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 Kullanım\nexport default withAuth(async (req, res) => {\n  \u002F\u002F Handler req.user'a erişebilir\n})\n```\n\n## Veritabanı Kalıpları\n\n### Sorgu Optimizasyonu\n\n```typescript\n\u002F\u002F PASS: İYİ: Sadece gerekli sütunları seç\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 FAIL: KÖTÜ: Her şeyi seç\nconst { data } = await supabase\n  .from('markets')\n  .select('*')\n```\n\n### N+1 Sorgu Önleme\n\n```typescript\n\u002F\u002F FAIL: KÖTÜ: N+1 sorgu problemi\nconst markets = await getMarkets()\nfor (const market of markets) {\n  market.creator = await getUser(market.creator_id)  \u002F\u002F N sorgu\n}\n\n\u002F\u002F PASS: İYİ: Toplu getirme\nconst markets = await getMarkets()\nconst creatorIds = markets.map(m => m.creator_id)\nconst creators = await getUsers(creatorIds)  \u002F\u002F 1 sorgu\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 Kalıbı\n\n```typescript\nasync function createMarketWithPosition(\n  marketData: CreateMarketDto,\n  positionData: CreatePositionDto\n) {\n  \u002F\u002F Supabase transaction kullan\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 Supabase'de SQL fonksiyonu\nCREATE OR REPLACE FUNCTION create_market_with_position(\n  market_data jsonb,\n  position_data jsonb\n)\nRETURNS jsonb\nLANGUAGE plpgsql\nAS $$\nBEGIN\n  -- Transaction otomatik başlar\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 otomatik olur\n    RETURN jsonb_build_object('success', false, 'error', SQLERRM);\nEND;\n$$;\n```\n\n## Önbellekleme Stratejileri\n\n### Redis Önbellekleme Katmanı\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 Önce önbelleği kontrol et\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 - veritabanından getir\n    const market = await this.baseRepo.findById(id)\n\n    if (market) {\n      \u002F\u002F 5 dakika önbellekle\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 Kalıbı\n\n```typescript\nasync function getMarketWithCache(id: string): Promise\u003CMarket> {\n  const cacheKey = `market:${id}`\n\n  \u002F\u002F Önbelleği dene\n  const cached = await redis.get(cacheKey)\n  if (cached) return JSON.parse(cached)\n\n  \u002F\u002F Cache miss - DB'den getir\n  const market = await db.markets.findUnique({ where: { id } })\n\n  if (!market) throw new Error('Market not found')\n\n  \u002F\u002F Önbelleği güncelle\n  await redis.setex(cacheKey, 300, JSON.stringify(market))\n\n  return market\n}\n```\n\n## Hata Yönetimi Kalıpları\n\n### Merkezi Hata Yöneticisi\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 Beklenmeyen hataları logla\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 Kullanım\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### Exponential Backoff ile Tekrar Deneme\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 Kullanım\nconst data = await fetchWithRetry(() => fetchFromAPI())\n```\n\n## Kimlik Doğrulama ve Yetkilendirme\n\n### JWT Token Doğrulama\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 API route'unda kullanım\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### Rol Tabanlı Erişim Kontrolü\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 Kullanım - HOF handler'ı sarar\nexport const DELETE = requirePermission('delete')(\n  async (request: Request, user: User) => {\n    \u002F\u002F Handler doğrulanmış yetki ile kullanıcı alır\n    return new Response('Deleted', { status: 200 })\n  }\n)\n```\n\n## Rate Limiting\n\n### Basit 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 Pencere dışındaki eski istekleri kaldır\n    const recentRequests = requests.filter(time => now - time \u003C windowMs)\n\n    if (recentRequests.length >= maxRequests) {\n      return false  \u002F\u002F Rate limit aşıldı\n    }\n\n    \u002F\u002F Mevcut isteği ekle\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\u002Fdak\n\n  if (!allowed) {\n    return NextResponse.json({\n      error: 'Rate limit exceeded'\n    }, { status: 429 })\n  }\n\n  \u002F\u002F İstekle devam et\n}\n```\n\n## Arka Plan İşleri ve Kuyruklar\n\n### Basit Kuyruk Kalıbı\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 İş yürütme mantığı\n  }\n}\n\n\u002F\u002F Market indeksleme için kullanım\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 Bloke etmek yerine kuyruğa ekle\n  await indexQueue.add({ marketId })\n\n  return NextResponse.json({ success: true, message: 'Job queued' })\n}\n```\n\n## Loglama ve İzleme\n\n### Yapılandırılmış Loglama\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 Kullanım\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**Unutmayın**: Backend kalıpları ölçeklenebilir, sürdürülebilir sunucu tarafı uygulamalar sağlar. Karmaşıklık seviyenize uyan kalıpları seçin.\n","# Backend Geliştirme Kalıpları\n\nÖlçeklenebilir sunucu tarafı uygulamalar için backend mimari kalıpları ve en iyi uygulamalar.\n\n## Ne Zaman Aktifleştirmelisiniz\n\n- REST veya GraphQL API endpoint'leri tasarlarken\n- Repository, service veya controller katmanları uygularken\n- Veritabanı sorgularını optimize ederken (N+1, indeksleme, bağlantı havuzu)\n- Önbellekleme eklerken (Redis, in-memory, HTTP cache başlıkları)\n- Arka plan işleri veya async işleme ayarlarken\n- API'ler için hata yönetimi ve doğrulama yapılandırırken\n- Middleware oluştururken (auth, logging, rate limiting)\n\n## API Tasarım Kalıpları\n\n### RESTful API Yapısı\n\n```typescript\n\u002F\u002F PASS: Kaynak tabanlı URL'ler\nGET    \u002Fapi\u002Fmarkets                 # Kaynakları listele\nGET    \u002Fapi\u002Fmarkets\u002F:id             # Tek kaynak getir\nPOST   \u002Fapi\u002Fmarkets                 # Kaynak oluştur\nPUT    \u002Fapi\u002Fmarkets\u002F:id             # Kaynağı değiştir (tam)\nPATCH  \u002Fapi\u002Fmarkets\u002F:id             # Kaynağı güncelle (kısmi)\nDELETE \u002Fapi\u002Fmarkets\u002F:id             # Kaynağı sil\n\n\u002F\u002F PASS: Filtreleme, sıralama, sayfalama için query parametreleri\nGET \u002Fapi\u002Fmarkets?status=active&sort=volume&limit=20&offset=0\n```\n\n### Repository Kalıbı\n\n```typescript\n\u002F\u002F Veri erişim mantığını soyutla\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 Diğer metodlar...\n}\n```\n\n### Service Katmanı Kalıbı\n\n```typescript\n\u002F\u002F İş mantığı veri erişiminden ayrılmış\nclass MarketService {\n  constructor(private marketRepo: MarketRepository) {}\n\n  async searchMarkets(query: string, limit: number = 10): Promise\u003CMarket[]> {\n    \u002F\u002F İş mantığı\n    const embedding = await generateEmbedding(query)\n    const results = await this.vectorSearch(embedding, limit)\n\n    \u002F\u002F Tam veriyi getir\n    const markets = await this.marketRepo.findByIds(results.map(r => r.id))\n\n    \u002F\u002F Benzerliğe göre sırala\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 arama implementasyonu\n  }\n}\n```\n\n### Middleware Kalıbı\n\n```typescript\n\u002F\u002F Request\u002Fresponse işleme hattı\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 Kullanım\nexport default withAuth(async (req, res) => {\n  \u002F\u002F Handler req.user'a erişebilir\n})\n```\n\n## Veritabanı Kalıpları\n\n### Sorgu Optimizasyonu\n\n```typescript\n\u002F\u002F PASS: İYİ: Sadece gerekli sütunları seç\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 FAIL: KÖTÜ: Her şeyi seç\nconst { data } = await supabase\n  .from('markets')\n  .select('*')\n```\n\n### N+1 Sorgu Önleme\n\n```typescript\n\u002F\u002F FAIL: KÖTÜ: N+1 sorgu problemi\nconst markets = await getMarkets()\nfor (const market of markets) {\n  market.creator = await getUser(market.creator_id)  \u002F\u002F N sorgu\n}\n\n\u002F\u002F PASS: İYİ: Toplu getirme\nconst markets = await getMarkets()\nconst creatorIds = markets.map(m => m.creator_id)\nconst creators = await getUsers(creatorIds)  \u002F\u002F 1 sorgu\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 Kalıbı\n\n```typescript\nasync function createMarketWithPosition(\n  marketData: CreateMarketDto,\n  positionData: CreatePositionDto\n) {\n  \u002F\u002F Supabase transaction kullan\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 Supabase'de SQL fonksiyonu\nCREATE OR REPLACE FUNCTION create_market_with_position(\n  market_data jsonb,\n  position_data jsonb\n)\nRETURNS jsonb\nLANGUAGE plpgsql\nAS $$\nBEGIN\n  -- Transaction otomatik başlar\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 otomatik olur\n    RETURN jsonb_build_object('success', false, 'error', SQLERRM);\nEND;\n$$;\n```\n\n## Önbellekleme Stratejileri\n\n### Redis Önbellekleme Katmanı\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 Önce önbelleği kontrol et\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 - veritabanından getir\n    const market = await this.baseRepo.findById(id)\n\n    if (market) {\n      \u002F\u002F 5 dakika önbellekle\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 Kalıbı\n\n```typescript\nasync function getMarketWithCache(id: string): Promise\u003CMarket> {\n  const cacheKey = `market:${id}`\n\n  \u002F\u002F Önbelleği dene\n  const cached = await redis.get(cacheKey)\n  if (cached) return JSON.parse(cached)\n\n  \u002F\u002F Cache miss - DB'den getir\n  const market = await db.markets.findUnique({ where: { id } })\n\n  if (!market) throw new Error('Market not found')\n\n  \u002F\u002F Önbelleği güncelle\n  await redis.setex(cacheKey, 300, JSON.stringify(market))\n\n  return market\n}\n```\n\n## Hata Yönetimi Kalıpları\n\n### Merkezi Hata Yöneticisi\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 Beklenmeyen hataları logla\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 Kullanım\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### Exponential Backoff ile Tekrar Deneme\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 Kullanım\nconst data = await fetchWithRetry(() => fetchFromAPI())\n```\n\n## Kimlik Doğrulama ve Yetkilendirme\n\n### JWT Token Doğrulama\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 API route'unda kullanım\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### Rol Tabanlı Erişim Kontrolü\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 Kullanım - HOF handler'ı sarar\nexport const DELETE = requirePermission('delete')(\n  async (request: Request, user: User) => {\n    \u002F\u002F Handler doğrulanmış yetki ile kullanıcı alır\n    return new Response('Deleted', { status: 200 })\n  }\n)\n```\n\n## Rate Limiting\n\n### Basit 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 Pencere dışındaki eski istekleri kaldır\n    const recentRequests = requests.filter(time => now - time \u003C windowMs)\n\n    if (recentRequests.length >= maxRequests) {\n      return false  \u002F\u002F Rate limit aşıldı\n    }\n\n    \u002F\u002F Mevcut isteği ekle\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\u002Fdak\n\n  if (!allowed) {\n    return NextResponse.json({\n      error: 'Rate limit exceeded'\n    }, { status: 429 })\n  }\n\n  \u002F\u002F İstekle devam et\n}\n```\n\n## Arka Plan İşleri ve Kuyruklar\n\n### Basit Kuyruk Kalıbı\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 İş yürütme mantığı\n  }\n}\n\n\u002F\u002F Market indeksleme için kullanım\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 Bloke etmek yerine kuyruğa ekle\n  await indexQueue.add({ marketId })\n\n  return NextResponse.json({ success: true, message: 'Job queued' })\n}\n```\n\n## Loglama ve İzleme\n\n### Yapılandırılmış Loglama\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 Kullanım\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**Unutmayın**: Backend kalıpları ölçeklenebilir, sürdürülebilir sunucu tarafı uygulamalar sağlar. Karmaşıklık seviyenize uyan kalıpları seçin.\n",{"name":5,"origin":24,"description":7},"ECC","master","d6ca01da0f24a3b0e26e4a8b7b66cbd25d429f5d","skills\u002Feverything-claude-code\u002Fdocs\u002Ftr\u002Fskills\u002Fbackend-patterns",0,"https:\u002F\u002Fgithub.com\u002FSriramGandhiS\u002FSkills","https:\u002F\u002Fgithub.com\u002FSriramGandhiS","https:\u002F\u002Fsriram.website\u002F","Curious guy who keeps tinkering until something works","2026-05-20 16:21:34",{"source":8,"skillName":5,"commands":35,"prompt":45,"zipAvailable":46},[36,39,42],{"tool":37,"command":38},"npx","npx skills add SriramGandhiS\u002FSkills --skill backend-patterns",{"tool":40,"command":41},"bunx","bunx skills add SriramGandhiS\u002FSkills --skill backend-patterns",{"tool":43,"command":44},"pnpm","pnpm dlx skills add SriramGandhiS\u002FSkills --skill backend-patterns","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002FSriramGandhiS\u002FSkills\u002Fblob\u002Fmaster\u002Fskills\u002Feverything-claude-code\u002Fdocs\u002Ftr\u002Fskills\u002Fbackend-patterns\u002FSKILL.md",true,[],[49,56,61,67,74,81],{"skillNo":50,"name":51,"nameZh":6,"description":52,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":53,"categories":54,"keywords":55,"publishedAt":19},"01M732609EPJWV13PVTX3GT4TM","webgpu-threejs-tsl","Comprehensive guide for developing WebGPU-enabled Three.js applications using TSL (Three.js Shading Language). Covers WebGPU renderer setup, TSL syntax and node materials, compute shaders, post-processing effects, and WGSL integration. Use this skill when working with Three.js WebGPU, TSL shaders, node materials, or GPU compute in Three.js.","https:\u002F\u002Fgithub.com\u002FSriramGandhiS\u002FSkills\u002Fblob\u002Fmaster\u002Fwebgpu-threejs-tsl\u002Fskills\u002Fwebgpu-threejs-tsl\u002FSKILL.md",[],[],{"skillNo":57,"name":51,"nameZh":6,"description":52,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":58,"categories":59,"keywords":60,"publishedAt":19},"01M7325XM47AGWB6K6C4VXKE6B","https:\u002F\u002Fgithub.com\u002FSriramGandhiS\u002FSkills\u002Fblob\u002Fmaster\u002Fwebgpu-threejs-tsl\u002FSKILL.md",[],[],{"skillNo":62,"name":63,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":64,"categories":65,"keywords":66,"publishedAt":19},"01M7325WP6DES69JKC840VMFEP","verification-loop","https:\u002F\u002Fgithub.com\u002FSriramGandhiS\u002FSkills\u002Fblob\u002Fmaster\u002Fweb-assets\u002Fdocs\u002Fzh-TW\u002Fskills\u002Fverification-loop\u002FSKILL.md",[],[],{"skillNo":68,"name":69,"nameZh":6,"description":70,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":71,"categories":72,"keywords":73,"publishedAt":19},"01M7325TFQF1DZTQ6J3WGQQ1VR","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\u002FSriramGandhiS\u002FSkills\u002Fblob\u002Fmaster\u002Fweb-assets\u002Fdocs\u002Fzh-TW\u002Fskills\u002Ftdd-workflow\u002FSKILL.md",[],[],{"skillNo":75,"name":76,"nameZh":6,"description":77,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":78,"categories":79,"keywords":80,"publishedAt":19},"01M7325RGV9AY9PK92D2V8KKPW","strategic-compact","Suggests manual context compaction at logical intervals to preserve context through task phases rather than arbitrary auto-compaction.","https:\u002F\u002Fgithub.com\u002FSriramGandhiS\u002FSkills\u002Fblob\u002Fmaster\u002Fweb-assets\u002Fdocs\u002Fzh-TW\u002Fskills\u002Fstrategic-compact\u002FSKILL.md",[],[],{"skillNo":82,"name":83,"nameZh":6,"description":84,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":85,"categories":86,"keywords":87,"publishedAt":19},"01M7325MZC28SE86E7NMCNEFS4","security-review","Use this skill when adding authentication, handling user input, working with secrets, creating API endpoints, or implementing payment\u002Fsensitive features. Provides comprehensive security checklist and patterns.","https:\u002F\u002Fgithub.com\u002FSriramGandhiS\u002FSkills\u002Fblob\u002Fmaster\u002Fweb-assets\u002Fdocs\u002Fzh-TW\u002Fskills\u002Fsecurity-review\u002FSKILL.md",[],[]]