backend-patterns
Backend architecture patterns, API design, database optimization, and server-side best practices for Node.js, Express, and Next.js API routes.
DeepseekModel
Curated skill
Quality Excellent · 90
v1.0.0
Get
https://deepseekmodel.com/api/download.php?id=affaan-m-ecc-docs-ja-jp-skills-backend-patterns-skill-md&format=skill
Download .skill
Standard format with system_prompt and model_config, ready for any agent framework
The actual content of the system_prompt field in the .skill file.
name backend-patterns description Backend architecture patterns, API design, database optimization, and server-side best practices for Node.js, Express, and Next.js API routes. バックエンド開発パターン スケーラブルなサーバーサイドアプリケーションのためのバックエンドアーキテクチャパターンとベストプラクティス。 API設計パターン RESTful API構造 // PASS: リソースベースのURL GET /api/markets # リソースのリスト GET /api/markets/:id # 単一リソースの取得 POST /api/markets # リソースの作成 PUT /api/markets/:id # リソースの置換 PATCH /api/markets/:id # リソースの更新 DELETE /api/markets/:id # リソースの削除 // PASS: フィルタリング、ソート、ページネーション用のクエリパラメータ GET /api/markets?status=active&sort=volume&limit= 20 &offset= 0 リポジトリパターン // データアクセスロジックの抽象化 interface MarketRepository { findAll ( filters ?: MarketFilters ): Promise < Market []> findById ( id : string ): Promise < Market | null > create ( data : CreateMarketDto ): Promise < Market > update ( id : string , data : UpdateMarketDto ): Promise < Market > delete ( id : string ): Promise < void > } class SupabaseMarketRepository implements MarketRepository { async findAll ( filters ?: MarketFilters ): Promise < Market []> { let query = supabase. from ( 'markets' ). select ( '*' ) if (filters?. status ) { query = query. eq ( 'status' , filters. status ) } if (filters?. limit ) { query = query. limit (filters. limit ) } const { data, error } = await query if (error) throw new Error (error. message ) return data } // その他のメソッド... } サービスレイヤーパターン // ビジネスロジックをデータアクセスから分離 class MarketService { constructor ( private marketRepo : MarketRepository ) {} async searchMarkets ( query : string , limit : number = 10 ): Promise < Market []> { // ビジネスロジック const embedding = await generateEmbedding (query) const results = await this . vectorSearch (embedding, limit) // 完全なデータを取得 const markets = await this . marketRepo . findByIds (results. map ( r => r. id )) // 類似度でソート return markets. sort ( ( a, b ) => { const scoreA = results. find ( r => r. id === a. id )?. score || 0 const scoreB = results. find ( r => r. id === b. id )?. score || 0 return scoreA - scoreB }) } private async vectorSearch ( embedding : number [], limit : number ) { // ベクトル検索の実装 } } ミドルウェアパターン // リクエスト/レスポンス処理パイプライン export function withAuth ( handler : NextApiHandler ): NextApiHandler { return async (req, res) => { const token = req. headers . authorization ?. replace ( 'Bearer ' , '' ) if (!token) { return res. status ( 401 ). json ({ error : 'Unauthorized' }) } try { const user = await verifyToken (token) req. user = user return handler (req, res) } catch (error) { return res. status ( 401 ). json ({ error : 'Invalid token' }) } } } // 使用方法 export default withAuth ( async (req, res) => { // ハンドラーはreq.userにアクセス可能 }) データベースパターン クエリ最適化 // PASS: 良い: 必要な列のみを選択 const { data } = await supabase . from ( 'markets' ) . select ( 'id, name, status, volume' ) . eq ( 'status' , 'active' ) . order ( 'volume' , { ascending : false }) . limit ( 10 ) // FAIL: 悪い: すべてを選択 const { data } = await supabase . from ( 'markets' ) . select ( '*' ) N+1クエリ防止 // FAIL: 悪い: N+1クエリ問題 const markets = await getMarkets () for ( const market of markets) { market. creator = await getUser (market. creator_id ) // Nクエリ } // PASS: 良い: バッチフェッチ const markets = await getMarkets () const creatorIds = markets. map ( m => m. creator_id ) const creators = await getUsers (creatorIds) // 1クエリ const creatorMap = new Map (creators. map ( c => [c. id , c])) markets. forEach ( market => { market. creator = creatorMap. get (market. creator_id ) }) トランザクションパターン async function createMarketWithPosition ( marketData : CreateMarketDto , positionData : CreatePositionDto ) { // Supabaseトランザクションを使用 const { data, error } = await supabase. rpc ( 'create_market_with_position' , { market_data : marketData, position_data : positionData }) if (error) throw new Error ( 'Transaction failed' ) return data } // SupabaseのSQL関数 CREATE OR REPLACE FUNCTION create_market_with_position ( market_data jsonb, position_data jsonb ) RETURNS jsonb LANGUAGE plpgsql AS $$ BEGIN -- トランザクションは自動的に開始 INSERT INTO markets VALUES (market_data); INSERT INTO positions VALUES (position_data); RETURN jsonb_build_object ( 'success' , true ); EXCEPTION WHEN OTHERS THEN -- ロールバックは自動的に発生 RETURN jsonb_build_object ( 'success' , false , 'error' , SQLERRM ); END ; $$; キャッシング戦略 Redisキャッシングレイヤー class CachedMarketRepository implements MarketRepository { constructor ( private baseRepo : MarketRepository , private redis : RedisClient ) {} async findById ( id : string ): Promise < Market | null > { // 最初にキャッシュをチェック const cached = await this . redis . get ( `market: ${id} ` ) if (cached) { return JSON . parse (cached) } // キャッシュミス - データベースから取得 const market = await this . baseRepo . findById (id) if (market) { // 5分間キャッシュ await this . redis . setex ( `market: ${id} ` , 300 , JSON . stringify (market)) } return market } async invalidateCache ( id : string ): Promise < void > { await this . redis . del ( `market: ${id} ` ) } } Cache-Asideパターン async function getMarketWithCache ( id : string ): Promise < Market > { const cacheKey = `market: ${id} ` // キャッシュを試す const cached = await redis. get (cacheKey) if (cached) return JSON . parse (cached) // キャッシュミス - DBから取得 const market = await db. markets . findUnique ({ where : { id } }) if (!market) throw new Error ( 'Market not found' ) // キャッシュを更新 await redis. setex (cacheKey, 300 , JSON . stringify (market)) return market } エラーハンドリングパターン 集中エラーハンドラー class ApiError extends Error { constructor ( public statusCode : number , public message : string , public isOperational = true ) { super (message) Object . setPrototypeOf ( this , ApiError . prototype ) } } export function errorHandler ( error : unknown , req : Request ): Response { if (error instanceof ApiError ) { return NextResponse . json ({ success : false , error : error. message }, { status : error. statusCode }) } if (error instanceof z. ZodError ) { return NextResponse . json ({ success : false , error : 'Validation failed' , details : error. errors }, { status : 400 }) } // 予期しないエラーをログに記録 console . error ( 'Unexpected error:' , error) return NextResponse . json ({ success : false , error : 'Internal server error' }, { status : 500 }) } // 使用方法 export async function GET ( request : Request ) { try { const data = await fetchData () return NextResponse . json ({ success : true , data }) } catch (error) { return errorHandler (error, request) } } 指数バックオフによるリトライ async function fetchWithRetry<T>( fn : () => Promise <T>, maxRetries = 3 ): Promise <T> { let lastError : Error for ( let i = 0 ; i < maxRetries; i++) { try { return await fn () } catch (error) { lastError = error as Error if (i < maxRetries - 1 ) { // 指数バックオフ: 1秒、2秒、4秒 const delay = Math . pow ( 2 , i) * 1000 await new Promise ( resolve => setTimeout (resolve, delay)) } } } throw lastError! } // 使用方法 const data = await fetchWithRetry ( () => fetchFromAPI ()) 認証と認可 JWTトークン検証 import jwt from 'jsonwebtoken' interface JWTPayload { userId : string email : string role : 'admin' | 'user' } export function verifyToken ( token : string ): JWTPayload { try { const payload = jwt. verify (token, process. env . JWT_SECRET !) as JWTPayload return payload } catch (error) { throw new ApiError ( 401 , 'Invalid token' ) } } export async function requireAuth ( request : Request ) { const token = request. headers . get ( 'authorization' )?. replace ( 'Bearer ' , '' ) if (!token) { throw new ApiError ( 401 , 'Missing authorization token' ) } return verifyToken (token) } // APIルートでの使用方法 export async function GET ( request : Request ) { const user = await requireAuth (request) const data = await getDataForUser (user. userId ) return NextResponse . json ({ success : true , data }) } ロールベースアクセス制御 type Permission = 'read' | 'write' | 'delete' | 'admin' interface User { id : string role : 'admin' | 'moderator' | 'user' } const rolePermissions : Record < User [ 'role' ], Permission []> = { admin : [ 'read' , 'write' , 'delete' , 'admin' ], moderator : [ 'read' , 'write' , 'delete' ], user : [ 'read' , 'write' ] } export function hasPermission ( user : User , permission : Permission ): boolean { return rolePermissions[user. role ]. includes (permission) } export function requirePermission ( permission : Permission ) { return ( handler : (request: Request, user: User) => Promise < Response > ) => { return async ( request : Request ) => { const user = await requireAuth (request) if (! hasPermission (user, permission)) { throw new ApiError ( 403 , 'Insufficient permissions' ) } return handler (request, user) } } } // 使用方法 - HOFがハンドラーをラップ export const DELETE = requirePermission ( 'delete' )( async ( request : Request , user : User ) => { // ハンドラーは検証済みの権限を持つ認証済みユーザーを受け取る return new Response ( 'Deleted' , { status : 200 }) } ) レート制限 シンプルなインメモリレートリミッター class RateLimiter { private requests = new Map < string , number []>() async checkLimit ( identifier : string , maxRequests : number , windowMs : number ): Promise < boolean > { const now = Date . now () const requests = this . requests . get (identifier) || [] // ウィンドウ外の古いリクエストを削除 const recentRequests = requests. filter ( time => now - time < windowMs) if (recentRequests. length >= maxRequests) { return false // レート制限超過 } // 現在のリクエストを追加 recentRequests. push (now) this . requests . set (identifier, recentRequests) return true } } const limiter = new RateLimiter () export async function GET ( request : Request ) { const ip = request. headers . get ( 'x-forwarded-for' ) || 'unknown' const allowed = await limiter. checkLimit (ip, 100 , 60000 ) // 100 req/分 if (!allowed) { return NextResponse . json ({ error : 'Rate limit exceeded' }, { status : 429 }) } // リクエストを続行 } バックグラウンドジョブとキュー シンプルなキューパターン class JobQueue <T> { private queue : T[] = [] private processing = false async add ( job : T): Promise < void > { this . queue . push (job) if (! this . processing ) { this . process () } } private async process (): Promise < void > { this . processing = true while ( this . queue . length > 0 ) { const job = this . queue . shift ()! try { await this . execute (job) } catch (error) { console . error ( 'Job failed:' , error) } } this . processing = false } private async execute ( job : T): Promise < void > { // ジョブ実行ロジック } } // マーケットインデックス作成用の使用方法 interface IndexJob { marketId : string } const indexQueue = new JobQueue < IndexJob >() export async function POST ( request : Request ) { const { marketId } = await request. json () // ブロッキングの代わりにキューに追加 await indexQueue. add ({ marketId })
Keywords that activate this skill. Click one to copy it.
This skill does not provide trigger words.
The downloaded .skill package contains the following fields.
| Field | Description |
|---|---|
| format | Format tag (skill/v1) |
| skill_id | Unique skill ID |
| name | Skill name |
| version | Version |
| description | Description |
| category | Categories (array) |
| trigger_words | Trigger words |
| tags | Tags |
| source | Source |
| source_url | Source URL (this page) |
| exported_at | Exported at (set per download) |
| system_prompt | System prompt body |
| model_config | Model config: provider / model / temperature / max_tokens / top_p |
| examples | Examples |
| install_guide | Import guide for Coze / Dify / Claude / custom frameworks |
The same skill can be exported in different platform formats.