Awesome-omni-skill backend-architect
Design RESTful APIs, microservice boundaries, and database schemas. Use when designing API endpoints, planning service architecture, creating database schemas, implementing caching strategies, or setting up authentication patterns.
install
source · Clone the upstream repo
git clone https://github.com/diegosouzapw/awesome-omni-skill
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/diegosouzapw/awesome-omni-skill "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/development/backend-architect-arosenkranz" ~/.claude/skills/diegosouzapw-awesome-omni-skill-backend-architect && rm -rf "$T"
manifest:
skills/development/backend-architect-arosenkranz/SKILL.mdsource content
Backend Architect
Guidelines for scalable API design and microservices architecture.
Core Principles
- Clear service boundaries - Each service owns its data
- Contract-first APIs - Design before implementation
- Data consistency - Understand CAP tradeoffs
- Plan for scale - Horizontal scaling from day one
- Keep it simple - Avoid premature optimization
RESTful API Design
Resource Naming
# Good - nouns, plural, hierarchical GET /users GET /users/{id} GET /users/{id}/orders POST /users/{id}/orders GET /orders/{id}/items # Bad - verbs, singular, flat GET /getUser POST /createOrder GET /user-order-list
HTTP Methods
| Method | Purpose | Idempotent | Body |
|---|---|---|---|
| GET | Read resource | Yes | No |
| POST | Create resource | No | Yes |
| PUT | Replace resource | Yes | Yes |
| PATCH | Partial update | No | Yes |
| DELETE | Remove resource | Yes | No |
Response Codes
200 OK - Successful GET/PUT/PATCH 201 Created - Successful POST (include Location header) 204 No Content - Successful DELETE 400 Bad Request - Invalid input 401 Unauthorized - Missing/invalid auth 403 Forbidden - Valid auth, insufficient permissions 404 Not Found - Resource doesn't exist 409 Conflict - State conflict (duplicate, version mismatch) 422 Unprocessable - Valid syntax, invalid semantics 429 Too Many Reqs - Rate limited 500 Internal Error - Server error (log details, return generic msg)
Request/Response Format
// POST /users { "email": "user@example.com", "name": "John Doe", "role": "member" } // Response 201 Created { "id": "usr_abc123", "email": "user@example.com", "name": "John Doe", "role": "member", "createdAt": "2024-01-15T10:30:00Z", "updatedAt": "2024-01-15T10:30:00Z" } // Error Response { "error": { "code": "VALIDATION_ERROR", "message": "Invalid request parameters", "details": [ { "field": "email", "message": "Invalid email format" } ] } }
Pagination
GET /users?page=2&limit=20 GET /users?cursor=eyJpZCI6MTAwfQ&limit=20 Response: { "data": [...], "pagination": { "total": 150, "page": 2, "limit": 20, "hasMore": true, "nextCursor": "eyJpZCI6MTIwfQ" } }
Filtering and Sorting
GET /orders?status=pending&createdAfter=2024-01-01 GET /orders?sort=-createdAt,+total GET /users?fields=id,name,email
API Versioning
# URL path (recommended) GET /v1/users GET /v2/users # Header GET /users Accept: application/vnd.api+json;version=2 # Query param GET /users?version=2
Database Schema Design
Users and Auth
CREATE TABLE users ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), email VARCHAR(255) UNIQUE NOT NULL, email_verified_at TIMESTAMPTZ, password_hash VARCHAR(255) NOT NULL, created_at TIMESTAMPTZ DEFAULT NOW(), updated_at TIMESTAMPTZ DEFAULT NOW() ); CREATE TABLE sessions ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), user_id UUID REFERENCES users(id) ON DELETE CASCADE, token_hash VARCHAR(255) UNIQUE NOT NULL, expires_at TIMESTAMPTZ NOT NULL, created_at TIMESTAMPTZ DEFAULT NOW(), INDEX idx_sessions_user (user_id), INDEX idx_sessions_expires (expires_at) );
Soft Deletes
ALTER TABLE users ADD COLUMN deleted_at TIMESTAMPTZ; -- Query active users SELECT * FROM users WHERE deleted_at IS NULL; -- Create view for convenience CREATE VIEW active_users AS SELECT * FROM users WHERE deleted_at IS NULL;
Optimistic Locking
ALTER TABLE orders ADD COLUMN version INTEGER DEFAULT 1; -- Update with version check UPDATE orders SET status = 'shipped', version = version + 1 WHERE id = $1 AND version = $2; -- If rows affected = 0, version conflict occurred
Microservice Patterns
Service Boundaries
┌─────────────────┐ ┌─────────────────┐ │ User Service │ │ Order Service │ │ - Registration │ │ - Cart │ │ - Auth │ │ - Checkout │ │ - Profile │ │ - History │ │ [users DB] │ │ [orders DB] │ └────────┬────────┘ └────────┬────────┘ │ │ └───────────┬───────────┘ │ ┌──────┴──────┐ │ API Gateway │ │ - Routing │ │ - Auth │ │ - Rate Lim │ └─────────────┘
Inter-Service Communication
Synchronous (HTTP/gRPC)
- Request/response pattern
- Use for queries, real-time needs
- Include timeouts and circuit breakers
Asynchronous (Message Queue)
- Event-driven pattern
- Use for commands, eventual consistency
- Enables loose coupling
Event-Driven Architecture
// Event structure interface DomainEvent { id: string; type: string; aggregateId: string; timestamp: string; data: unknown; } // OrderCreated event { "id": "evt_123", "type": "order.created", "aggregateId": "ord_456", "timestamp": "2024-01-15T10:30:00Z", "data": { "userId": "usr_789", "total": 99.99, "items": [...] } }
Caching Strategies
Cache-Aside Pattern
async function getUser(id: string): Promise<User> { // Check cache first const cached = await cache.get(`user:${id}`); if (cached) return JSON.parse(cached); // Cache miss - fetch from DB const user = await db.users.findById(id); // Populate cache await cache.set(`user:${id}`, JSON.stringify(user), 'EX', 3600); return user; }
Cache Invalidation
// Invalidate on write async function updateUser(id: string, data: Partial<User>) { await db.users.update(id, data); await cache.del(`user:${id}`); } // Use cache tags for related data await cache.set(`user:${id}`, data, { tags: [`user:${id}`, 'users'] }); await cache.invalidateTag('users'); // Clear all user caches
Authentication Patterns
JWT Structure
// Access Token (short-lived, 15min) { "sub": "usr_123", "email": "user@example.com", "roles": ["user"], "exp": 1705312200, "iat": 1705311300 } // Refresh Token (long-lived, stored in DB) { "sub": "usr_123", "jti": "tok_abc", // Unique ID for revocation "exp": 1707903300 }
Auth Flow
1. POST /auth/login → { accessToken, refreshToken } 2. GET /api/users (Authorization: Bearer <accessToken>) 3. POST /auth/refresh → { accessToken } (when expired) 4. POST /auth/logout → Revoke refresh token
Rate Limiting
// Token bucket algorithm interface RateLimiter { identifier: string; // IP or user ID maxRequests: number; // e.g., 100 windowMs: number; // e.g., 60000 (1 minute) } // Response headers X-RateLimit-Limit: 100 X-RateLimit-Remaining: 42 X-RateLimit-Reset: 1705312200
Health Checks
// GET /health { "status": "healthy", "version": "1.2.3", "timestamp": "2024-01-15T10:30:00Z", "checks": { "database": { "status": "up", "latency": 5 }, "cache": { "status": "up", "latency": 1 }, "queue": { "status": "up" } } }