Skip to main content

Agent Skills Framework Extension

Cloud-Native Patterns Skill

When to Use This Skill

Use this skill when implementing cloud native patterns patterns in your codebase.

How to Use This Skill

  1. Review the patterns and examples below
  2. Apply the relevant patterns to your implementation
  3. Follow the best practices outlined in this skill

12-factor app, serverless, auto-scaling, and cloud-native design patterns.

Core Capabilities

  1. 12-Factor App - Cloud-native application design
  2. Container Patterns - Sidecar, ambassador, adapter
  3. Auto-Scaling - HPA, VPA, custom metrics
  4. Health Management - Liveness, readiness, startup probes
  5. Graceful Operations - Shutdown, drainage, zero-downtime

12-Factor Application

// 1. Codebase - One codebase tracked in version control
// ✅ Single git repository per service

// 2. Dependencies - Explicitly declare and isolate dependencies
// package.json or requirements.txt

// 3. Config - Store config in the environment
// src/config/index.ts
export const config = {
port: parseInt(process.env.PORT || '3000'),
databaseUrl: process.env.DATABASE_URL!,
redisUrl: process.env.REDIS_URL!,
logLevel: process.env.LOG_LEVEL || 'info',

// Validate required config
validate() {
const required = ['DATABASE_URL', 'REDIS_URL'];
const missing = required.filter(key => !process.env[key]);
if (missing.length > 0) {
throw new Error(`Missing required environment variables: ${missing.join(', ')}`);
}
},
};

// 4. Backing Services - Treat backing services as attached resources
// src/services/database.ts
import { Pool } from 'pg';

export function createPool(connectionString: string): Pool {
return new Pool({
connectionString,
max: 20,
idleTimeoutMillis: 30000,
connectionTimeoutMillis: 2000,
});
}

// Connection URL can be swapped without code changes:
// DATABASE_URL=postgres://user:pass@localhost:5432/mydb (dev)
// DATABASE_URL=postgres://user:pass@prod-db:5432/mydb (prod)

// 5. Build, Release, Run - Strictly separate build and run stages
// Dockerfile
/*
FROM node:18-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build

FROM node:18-alpine
WORKDIR /app
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/node_modules ./node_modules
CMD ["node", "dist/index.js"]
*/

// 6. Processes - Execute the app as stateless processes
// ❌ Don't store session state in memory
// ✅ Use Redis for sessions
import session from 'express-session';
import RedisStore from 'connect-redis';

app.use(session({
store: new RedisStore({ client: redisClient }),
secret: process.env.SESSION_SECRET!,
resave: false,
saveUninitialized: false,
}));

// 7. Port Binding - Export services via port binding
// src/index.ts
const server = app.listen(config.port, () => {
console.log(`Server running on port ${config.port}`);
});

// 8. Concurrency - Scale out via the process model
// Kubernetes Deployment
/*
apiVersion: apps/v1
kind: Deployment
metadata:
name: api
spec:
replicas: 3 # Horizontal scaling
selector:
matchLabels:
app: api
template:
spec:
containers:
- name: api
image: api:latest
resources:
requests:
cpu: 100m
memory: 128Mi
limits:
cpu: 500m
memory: 512Mi
*/

// 9. Disposability - Fast startup and graceful shutdown
// src/graceful-shutdown.ts
export function setupGracefulShutdown(server: Server, pool: Pool): void {
let isShuttingDown = false;

const shutdown = async (signal: string) => {
if (isShuttingDown) return;
isShuttingDown = true;

console.log(`Received ${signal}, starting graceful shutdown...`);

// Stop accepting new connections
server.close(() => {
console.log('HTTP server closed');
});

// Allow in-flight requests to complete (30s timeout)
await new Promise(resolve => setTimeout(resolve, 30000));

// Close database connections
await pool.end();
console.log('Database pool closed');

process.exit(0);
};

process.on('SIGTERM', () => shutdown('SIGTERM'));
process.on('SIGINT', () => shutdown('SIGINT'));
}

// 10. Dev/Prod Parity - Keep development, staging, and production similar
// docker-compose.yml for local development mirrors production

// 11. Logs - Treat logs as event streams
// src/logging/logger.ts
import pino from 'pino';

export const logger = pino({
level: config.logLevel,
formatters: {
level: (label) => ({ level: label }),
},
timestamp: pino.stdTimeFunctions.isoTime,
});

// Don't manage log files - write to stdout, let platform handle

// 12. Admin Processes - Run admin tasks as one-off processes
// package.json scripts
/*
{
"scripts": {
"migrate": "node dist/scripts/migrate.js",
"seed": "node dist/scripts/seed.js",
"console": "node --experimental-repl-await dist/scripts/console.js"
}
}
*/

Container Patterns

Sidecar Pattern

# Logging sidecar
apiVersion: v1
kind: Pod
metadata:
name: app-with-logging-sidecar
spec:
containers:
- name: app
image: myapp:latest
volumeMounts:
- name: logs
mountPath: /var/log/app

- name: log-shipper
image: fluent-bit:latest
volumeMounts:
- name: logs
mountPath: /var/log/app
- name: fluent-bit-config
mountPath: /fluent-bit/etc/

volumes:
- name: logs
emptyDir: {}
- name: fluent-bit-config
configMap:
name: fluent-bit-config

Ambassador Pattern

# API gateway ambassador
apiVersion: v1
kind: Pod
metadata:
name: app-with-ambassador
spec:
containers:
- name: app
image: myapp:latest
ports:
- containerPort: 8080

- name: ambassador
image: envoyproxy/envoy:v1.25
ports:
- containerPort: 8443
volumeMounts:
- name: envoy-config
mountPath: /etc/envoy

volumes:
- name: envoy-config
configMap:
name: envoy-config

Health Checks

// src/health/checks.ts
import { Pool } from 'pg';
import Redis from 'ioredis';

interface HealthCheck {
name: string;
check: () => Promise<{ healthy: boolean; details?: unknown }>;
}

export class HealthChecker {
private checks: HealthCheck[] = [];

addCheck(check: HealthCheck): void {
this.checks.push(check);
}

async runAll(): Promise<{
status: 'healthy' | 'unhealthy';
checks: Record<string, { healthy: boolean; details?: unknown }>;
}> {
const results: Record<string, { healthy: boolean; details?: unknown }> = {};
let allHealthy = true;

for (const check of this.checks) {
try {
const result = await check.check();
results[check.name] = result;
if (!result.healthy) allHealthy = false;
} catch (error) {
results[check.name] = {
healthy: false,
details: error instanceof Error ? error.message : 'Unknown error',
};
allHealthy = false;
}
}

return {
status: allHealthy ? 'healthy' : 'unhealthy',
checks: results,
};
}
}

// Database health check
export function databaseCheck(pool: Pool): HealthCheck {
return {
name: 'database',
check: async () => {
const start = Date.now();
await pool.query('SELECT 1');
const latency = Date.now() - start;
return {
healthy: latency < 1000,
details: { latency_ms: latency },
};
},
};
}

// Redis health check
export function redisCheck(redis: Redis): HealthCheck {
return {
name: 'redis',
check: async () => {
const start = Date.now();
await redis.ping();
const latency = Date.now() - start;
return {
healthy: latency < 100,
details: { latency_ms: latency },
};
},
};
}

// Memory health check
export function memoryCheck(maxHeapMB: number): HealthCheck {
return {
name: 'memory',
check: async () => {
const used = process.memoryUsage().heapUsed / 1024 / 1024;
return {
healthy: used < maxHeapMB,
details: { heap_used_mb: Math.round(used), max_mb: maxHeapMB },
};
},
};
}

// Express routes
import { Router } from 'express';

export function healthRoutes(checker: HealthChecker): Router {
const router = Router();

// Liveness - is the app running?
router.get('/health/live', (req, res) => {
res.status(200).json({ status: 'alive' });
});

// Readiness - is the app ready to serve traffic?
router.get('/health/ready', async (req, res) => {
const result = await checker.runAll();
const status = result.status === 'healthy' ? 200 : 503;
res.status(status).json(result);
});

// Startup - has the app completed initialization?
router.get('/health/startup', async (req, res) => {
const result = await checker.runAll();
const status = result.status === 'healthy' ? 200 : 503;
res.status(status).json(result);
});

return router;
}

Kubernetes Probes

apiVersion: apps/v1
kind: Deployment
metadata:
name: api
spec:
template:
spec:
containers:
- name: api
image: api:latest
ports:
- containerPort: 3000

# Startup probe - wait for app initialization
startupProbe:
httpGet:
path: /health/startup
port: 3000
failureThreshold: 30
periodSeconds: 10

# Liveness probe - restart if unhealthy
livenessProbe:
httpGet:
path: /health/live
port: 3000
initialDelaySeconds: 0
periodSeconds: 10
timeoutSeconds: 5
failureThreshold: 3

# Readiness probe - remove from load balancer if not ready
readinessProbe:
httpGet:
path: /health/ready
port: 3000
initialDelaySeconds: 0
periodSeconds: 5
timeoutSeconds: 3
failureThreshold: 3

# Lifecycle hooks
lifecycle:
preStop:
exec:
command: ["/bin/sh", "-c", "sleep 10"]

Auto-Scaling

# Horizontal Pod Autoscaler
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: api-hpa
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: api
minReplicas: 2
maxReplicas: 20
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 70
- type: Resource
resource:
name: memory
target:
type: Utilization
averageUtilization: 80
# Custom metrics (requests per second)
- type: Pods
pods:
metric:
name: http_requests_per_second
target:
type: AverageValue
averageValue: 1000
behavior:
scaleUp:
stabilizationWindowSeconds: 60
policies:
- type: Percent
value: 100
periodSeconds: 60
scaleDown:
stabilizationWindowSeconds: 300
policies:
- type: Percent
value: 10
periodSeconds: 60

Usage Examples

Implement 12-Factor App

Apply cloud-native-patterns skill to refactor application to follow 12-factor methodology

Add Health Checks

Apply cloud-native-patterns skill to implement liveness, readiness, and startup probes

Configure Auto-Scaling

Apply cloud-native-patterns skill to set up HPA with CPU, memory, and custom metrics

Integration Points

  • container-orchestration - Kubernetes deployment patterns
  • infrastructure-as-code - Terraform/Helm configuration
  • monitoring-observability - Metrics for auto-scaling

Success Output

When successful, this skill MUST output:

✅ SKILL COMPLETE: cloud-native-patterns

Completed:
- [x] 12-factor app principles applied (config in env, stateless processes)
- [x] Health checks implemented (liveness, readiness, startup probes)
- [x] Graceful shutdown configured (SIGTERM handling, connection drainage)
- [x] Auto-scaling configured (HPA with CPU/memory/custom metrics)
- [x] Container patterns implemented (sidecar/ambassador/adapter if applicable)
- [x] Kubernetes manifests validated and deployed

Outputs:
- config/index.ts (environment-based configuration)
- health/checks.ts (health check implementation)
- graceful-shutdown.ts (shutdown handler)
- k8s/deployment.yaml (Kubernetes deployment with probes)
- k8s/hpa.yaml (Horizontal Pod Autoscaler configuration)

Cloud-Native Compliance:
- 12-Factor Score: XX/12 factors implemented
- Health Checks: ✓ Liveness, ✓ Readiness, ✓ Startup
- Auto-Scaling: Min X replicas, Max X replicas
- Graceful Shutdown: XX second timeout

Completion Checklist

Before marking this skill as complete, verify:

  • Configuration stored in environment variables (not hardcoded)
  • All backing services treated as attached resources (swappable URLs)
  • Build/release/run stages strictly separated (Docker multi-stage build)
  • Application runs as stateless processes (no in-memory sessions)
  • Services exported via port binding (not relying on runtime injection)
  • Logs written to stdout (not managing log files)
  • Health check endpoints implemented (/health/live, /health/ready, /health/startup)
  • Graceful shutdown handler added (SIGTERM, SIGINT handling)
  • Kubernetes probes configured (liveness, readiness, startup)
  • Horizontal Pod Autoscaler configured with appropriate metrics
  • Resource requests/limits defined (CPU, memory)
  • Zero-downtime deployment tested (rolling updates without errors)

Failure Indicators

This skill has FAILED if:

  • ❌ Configuration hardcoded in code (not environment variables)
  • ❌ Application stores state in memory (sessions not externalized)
  • ❌ No health check endpoints (Kubernetes cannot determine pod health)
  • ❌ Graceful shutdown missing (connections dropped on SIGTERM)
  • ❌ Pods crash on startup (startup probe not configured)
  • ❌ Auto-scaling not working (HPA cannot read metrics)
  • ❌ Zero-downtime deployment fails (service interruption during rollout)
  • ❌ Resource limits not set (pod consumes all node resources)

When NOT to Use

Do NOT use this skill when:

  • Building monolithic applications not intended for cloud deployment
  • Legacy applications with hard dependencies on local filesystem/state
  • Applications requiring persistent local storage (not backing services)
  • Single-instance applications (no scaling requirements)
  • Use monolith-architecture-patterns for traditional deployments
  • Use serverless-patterns for event-driven, fully managed compute

Alternative skills for different deployment models:

  • serverless-patterns - AWS Lambda, Cloud Functions, Azure Functions
  • container-patterns - Docker without Kubernetes orchestration
  • vm-deployment-patterns - Traditional VM-based deployments

Anti-Patterns (Avoid)

Anti-PatternProblemSolution
Hardcoded configurationCannot deploy across environmentsUse environment variables, ConfigMaps, Secrets
Storing state in memoryHorizontal scaling impossibleExternalize state to Redis, database, or cache
Managing log filesContainer disk fills, logs lostWrite to stdout, let platform handle aggregation
No health checksKubernetes cannot detect failuresImplement /health/live and /health/ready endpoints
Abrupt shutdownConnections dropped, data lossHandle SIGTERM, drain connections gracefully
Fixed replica countCannot handle traffic spikesConfigure HPA with CPU/memory/custom metrics
No resource limitsNoisy neighbor, node exhaustionSet CPU/memory requests and limits
Tight coupling to backing servicesCannot swap database/cache providersUse connection strings from environment
Build artifacts in containerLarge image size, slow deploymentsMulti-stage Docker builds, separate build/run stages

Principles

This skill embodies CODITECT foundational principles:

#2 First Principles Thinking

  • 12-factor methodology based on cloud-native fundamentals
  • Stateless processes enable horizontal scaling
  • Treating logs as event streams (not files) aligns with distributed systems

#4 Separation of Concerns

  • Build stage separate from run stage (Docker multi-stage builds)
  • Configuration separate from code (environment variables)
  • Admin tasks as one-off processes (migrations, seeds separate from app)

#5 Eliminate Ambiguity

  • Clear health check semantics (liveness vs. readiness vs. startup)
  • Explicit resource requests/limits (not relying on defaults)
  • Documented graceful shutdown timeout (30s standard)

#7 Measurable Outcomes

  • Auto-scaling metrics (CPU %, memory %, requests/second)
  • Health check success rates (uptime monitoring)
  • Zero-downtime deployment verification (no 5xx errors during rollout)

#10 Automation First

  • Auto-scaling removes manual intervention (HPA)
  • Kubernetes self-healing (liveness probe restarts unhealthy pods)
  • Graceful shutdown automated (no manual connection drainage)

Full Principles: CODITECT-STANDARD-AUTOMATION.md


Version: 1.1.0 | Updated: 2026-01-04 | Author: CODITECT Team