Claude
Skills
Sign in
Back

backend-patterns

Included with Lifetime
$97 forever

Backend architecture patterns, API design, database optimization, and server-side best practices for Node.js, Express, NestJS, FastAPI, and Next.js API routes.

Design

What this skill does


# Backend Development Patterns

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

## Framework-Specific Guidelines

When working with specific frameworks, combine this skill with framework-specific skills:

| Framework       | Additional Skill              | When to Use                                                      |
| --------------- | ----------------------------- | ---------------------------------------------------------------- |
| **NestJS**      | `nestjs-best-practices` skill | Modules, Controllers, Providers, Guards, Interceptors, Pipes, DI |
| **FastAPI**     | `fastapi-templates` skill     | Routes, Decorators, DI, GraphQL, Microservices                   |
| **Next.js API** | This skill only               | Serverless API routes                                            |

### NestJS Integration

When using **NestJS**, the patterns in this skill should be adapted to NestJS conventions:

| Generic Pattern    | NestJS Implementation                                        |
| ------------------ | ------------------------------------------------------------ |
| Repository Pattern | Use `@Injectable()` repositories with DI                     |
| Service Layer      | Use `@Injectable()` services                                 |
| Middleware         | Use NestJS `@Injectable()` middleware or Guards/Interceptors |
| Error Handling     | Use Exception Filters (`@Catch()`)                           |
| Validation         | Use Pipes with `class-validator`                             |
| Auth Middleware    | Use Guards (`@UseGuards()`)                                  |
| Rate Limiting      | Use `@nestjs/throttler` module                               |

**Example - NestJS Repository Pattern:**

```typescript
// NestJS style with dependency injection
@Injectable()
export class MarketRepository {
  constructor(
    @InjectRepository(Market)
    private marketRepo: Repository<Market>,
  ) {}

  async findAll(filters?: MarketFilters): Promise<Market[]> {
    const query = this.marketRepo.createQueryBuilder('market');

    if (filters?.status) {
      query.where('market.status = :status', { status: filters.status });
    }

    return query.getMany();
  }
}

// Inject into service
@Injectable()
export class MarketService {
  constructor(private marketRepo: MarketRepository) {}
}
```

**Example - NestJS Error Handling:**

```typescript
// Exception filter instead of middleware error handler
@Catch()
export class AllExceptionsFilter implements ExceptionFilter {
  catch(exception: unknown, host: ArgumentsHost) {
    const ctx = host.switchToHttp();
    const response = ctx.getResponse<Response>();

    if (exception instanceof HttpException) {
      return response.status(exception.getStatus()).json({
        success: false,
        error: exception.message,
      });
    }

    return response.status(500).json({
      success: false,
      error: 'Internal server error',
    });
  }
}
```

> **Tip**: For NestJS-specific decorators, modules, and advanced features (GraphQL, Microservices, WebSockets), refer to the **nestjs skill** for detailed documentation.

## API Design Patterns

### RESTful API Structure

```typescript
// ✅ Resource-based URLs
GET    /api/markets                 # List resources
GET    /api/markets/:id             # Get single resource
POST   /api/markets                 # Create resource
PUT    /api/markets/:id             # Replace resource
PATCH  /api/markets/:id             # Update resource
DELETE /api/markets/:id             # Delete resource

// ✅ Query parameters for filtering, sorting, pagination
GET /api/markets?status=active&sort=volume&limit=20&offset=0
```

### Repository Pattern

```typescript
// Abstract data access logic
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;
  }

  // Other methods...
}
```

### Service Layer Pattern

```typescript
// Business logic separated from data access
class MarketService {
  constructor(private marketRepo: MarketRepository) {}

  async searchMarkets(query: string, limit: number = 10): Promise<Market[]> {
    // Business logic
    const embedding = await generateEmbedding(query);
    const results = await this.vectorSearch(embedding, limit);

    // Fetch full data
    const markets = await this.marketRepo.findByIds(results.map((r) => r.id));

    // Sort by similarity
    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) {
    // Vector search implementation
  }
}
```

### Middleware Pattern

```typescript
// Request/response processing pipeline
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' });
    }
  };
}

// Usage
export default withAuth(async (req, res) => {
  // Handler has access to req.user
});
```

## Database Patterns

### Query Optimization

```typescript
// ✅ GOOD: Select only needed columns
const { data } = await supabase
  .from('markets')
  .select('id, name, status, volume')
  .eq('status', 'active')
  .order('volume', { ascending: false })
  .limit(10);

// ❌ BAD: Select everything
const { data } = await supabase.from('markets').select('*');
```

### N+1 Query Prevention

```typescript
// ❌ BAD: N+1 query problem
const markets = await getMarkets();
for (const market of markets) {
  market.creator = await getUser(market.creator_id); // N queries
}

// ✅ GOOD: Batch fetch
const markets = await getMarkets();
const creatorIds = markets.map((m) => m.creator_id);
const creators = await getUsers(creatorIds); // 1 query
const creatorMap = new Map(creators.map((c) => [c.id, c]));

markets.forEach((market) => {
  market.creator = creatorMap.get(market.creator_id);
});
```

### Transaction Pattern

```typescript
async function createMarketWithPosition(
  marketData: CreateMarketDto,
  positionData: CreatePositionDto
) {
  // Use Supabase transaction
  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
}

// SQL function in Supabase
CREATE OR REPLACE FUNCTION create_market_with_position(
  market_data jsonb,
  position_data jsonb
)
RETURNS jsonb
LANGUAGE plpgsql
AS $$
BEGIN
  -- Start transaction automatically
  INSERT INTO markets VALUES (market_data);
  INSERT INTO positions VALUES (position_data);
  RETURN jsonb_build_object('success', true);
EXCEPTION
  WHEN OTHERS THEN
    -- Rollback happens automatically
    RETURN jsonb_build_object('success', false, 'error', SQLERRM);
END;
$$;
```

## Caching Strategies

### Redis Caching Layer

```typescript
class CachedMarketRepository implements MarketRepository {
  constructor(
    private baseRepo: MarketRepository,
    private redis: RedisClient,

Related in Design