Agent skill

fullstack-backend-master

Stars 163
Forks 31

Install this agent skill to your Project

npx add-skill https://github.com/majiayu000/claude-skill-registry/tree/main/skills/development/fullstack-backend-master

SKILL.md

Fullstack Backend Master

Expert-level guidance for building robust, scalable, production-ready backend systems.

Core Philosophy

Build for the unhappy path first. Errors, edge cases, and failures define production quality.

Optimize for debuggability. Structured logging, correlation IDs, and clear error messages save hours.

Security is non-negotiable. Input validation, parameterized queries, and principle of least privilege always.

API Design

REST Conventions

GET    /resources          → List (paginated)
GET    /resources/:id      → Get one
POST   /resources          → Create
PUT    /resources/:id      → Full update
PATCH  /resources/:id      → Partial update
DELETE /resources/:id      → Delete

# Nested resources
GET    /users/:userId/posts
POST   /users/:userId/posts

# Actions (when CRUD doesn't fit)
POST   /orders/:id/cancel
POST   /users/:id/verify-email

Response Structure

json
// Success
{
  "data": { ... },
  "meta": { "page": 1, "total": 100 }
}

// Error
{
  "error": {
    "code": "VALIDATION_ERROR",
    "message": "Email is required",
    "details": [{ "field": "email", "issue": "required" }]
  }
}

Status Codes

Code Use Case
200 Success with body
201 Created (return created resource)
204 Success, no content (DELETE)
400 Validation error (client's fault)
401 Not authenticated
403 Authenticated but not authorized
404 Resource not found
409 Conflict (duplicate, state conflict)
422 Unprocessable (valid JSON, invalid semantics)
429 Rate limited
500 Server error (never expose stack traces)

Database Design

Schema Principles

  1. Always include audit columns: created_at, updated_at, deleted_at (soft delete)
  2. UUID vs Integer IDs: UUIDs for distributed systems, integers for simplicity
  3. Normalize first, denormalize for performance: Start with 3NF, add caching/denormalization when measured
  4. Index strategically: Index foreign keys, frequently queried columns, composite indexes for multi-column WHERE

Migration Patterns

sql
-- Always reversible migrations
-- UP
ALTER TABLE users ADD COLUMN phone VARCHAR(20);

-- DOWN
ALTER TABLE users DROP COLUMN phone;

Query Optimization

  • Use EXPLAIN ANALYZE before production
  • Avoid SELECT * in application code
  • Use connection pooling (pgbouncer, HikariCP)
  • Implement pagination with cursor-based (keyset) for large datasets

Authentication & Authorization

Token Strategy

Access Token:  Short-lived (15-60 min), stateless JWT
Refresh Token: Long-lived (7-30 days), stored server-side, rotatable

JWT Best Practices

  • Sign with RS256 (asymmetric) for microservices, HS256 for monoliths
  • Include: sub, exp, iat, iss, roles/permissions
  • Never include: passwords, PII, sensitive data
  • Validate: signature, expiry, issuer, audience

Authorization Patterns

typescript
// Role-Based Access Control (RBAC)
interface Permission {
  resource: string;   // "posts"
  action: string;     // "create" | "read" | "update" | "delete"
}

// Attribute-Based Access Control (ABAC) - for complex rules
canEdit = (user.id === resource.ownerId) || user.roles.includes('admin');

Error Handling

Layered Error Strategy

typescript
// 1. Domain errors (business logic)
class InsufficientFundsError extends DomainError {
  constructor(public available: number, public requested: number) {
    super(`Insufficient funds: ${available} < ${requested}`);
  }
}

// 2. Application errors (mapped to HTTP)
class NotFoundError extends ApplicationError {
  statusCode = 404;
}

// 3. Global error handler
app.use((err, req, res, next) => {
  logger.error({ err, requestId: req.id, path: req.path });
  
  if (err instanceof ApplicationError) {
    return res.status(err.statusCode).json({ error: err.toJSON() });
  }
  
  // Never expose internal errors
  res.status(500).json({ error: { code: 'INTERNAL_ERROR', message: 'Something went wrong' } });
});

Logging & Observability

Structured Logging

typescript
// Always structured, never string concatenation
logger.info({
  event: 'order_created',
  orderId: order.id,
  userId: user.id,
  amount: order.total,
  duration: Date.now() - startTime
});

// Correlation ID for request tracing
const requestId = req.headers['x-request-id'] || uuid();
logger.child({ requestId });

Key Metrics

  • Latency: p50, p95, p99 response times
  • Error rate: 5xx / total requests
  • Throughput: requests/second
  • Saturation: CPU, memory, DB connections

Security Checklist

Category Requirement
Input Validate & sanitize all input (zod, joi)
SQL Parameterized queries ONLY, never string concat
Auth Hash passwords (bcrypt/argon2, cost ≥ 10)
HTTPS TLS 1.2+ everywhere, HSTS headers
Headers CSP, X-Frame-Options, X-Content-Type-Options
Secrets Environment variables, never in code
Rate Limit All endpoints, stricter on auth endpoints
CORS Whitelist specific origins, never * in prod

Testing Strategy

Test Pyramid

         /\
        /  \  E2E (few, slow, high confidence)
       /----\
      /      \ Integration (API, DB, external services)
     /--------\
    /          \ Unit (many, fast, isolated)
   /--------------\

Backend Test Patterns

typescript
// Unit: Pure functions, business logic
test('calculateDiscount applies 10% for orders over $100', () => {
  expect(calculateDiscount({ total: 150 })).toBe(15);
});

// Integration: Real DB, mocked external services
test('POST /orders creates order in database', async () => {
  const res = await request(app).post('/orders').send(orderData);
  expect(res.status).toBe(201);
  
  const order = await db.orders.findById(res.body.data.id);
  expect(order.total).toBe(orderData.total);
});

Performance Patterns

Caching Layers

  1. Application cache: In-memory (Redis) for hot data
  2. Database cache: Query result caching, materialized views
  3. HTTP cache: ETags, Cache-Control headers

Async Processing

typescript
// Offload slow operations to queue
await queue.add('send-email', { to: user.email, template: 'welcome' });
await queue.add('generate-report', { reportId }, { delay: 5000 });

// Process in workers
queue.process('send-email', async (job) => {
  await emailService.send(job.data);
});

Database Connection Pooling

typescript
// Node.js example
const pool = new Pool({
  max: 20,              // Max connections
  idleTimeoutMillis: 30000,
  connectionTimeoutMillis: 2000,
});

Architecture Patterns

Monolith First

Start monolithic, extract services ONLY when:

  • Team size requires independent deployability
  • Specific component has vastly different scaling needs
  • Clear bounded context with minimal cross-service calls

Service Communication

Pattern Use Case
REST/HTTP Synchronous, simple CRUD
gRPC High-performance, internal services
Message Queue Async, decoupled, retry-able
Event Sourcing Audit trail, complex state

File Organization

src/
├── api/
│   ├── routes/           # Route definitions
│   ├── controllers/      # Request handling
│   ├── middleware/       # Auth, validation, logging
│   └── validators/       # Request validation schemas
├── services/             # Business logic
├── repositories/         # Data access layer
├── models/               # Database models/entities
├── utils/                # Shared utilities
├── config/               # Environment config
└── types/                # TypeScript types

tests/
├── unit/
├── integration/
└── fixtures/

Quick References

  • Database optimization: See references/database-patterns.md
  • Auth implementation: See references/auth-patterns.md
  • Deployment checklist: See references/deployment.md

Didn't find tool you were looking for?

Be as detailed as possible for better results