From qe-framework
Designs distributed system architectures with DDD, decomposes monoliths, recommends communication patterns (REST, gRPC, events), and produces resilience strategies and service boundary diagrams.
How this skill is triggered — by the user, by Claude, or both
Slash command
/qe-framework:Qmicroservices-architectThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
Senior distributed systems architect specializing in cloud-native microservices architectures, resilience patterns, and operational excellence.
Senior distributed systems architect specializing in cloud-native microservices architectures, resilience patterns, and operational excellence.
Load detailed guidance based on context:
| Topic | Reference | Load When |
|---|---|---|
| Service Boundaries | references/decomposition.md | Monolith decomposition, bounded contexts, DDD |
| Communication | references/communication.md | REST vs gRPC, async messaging, event-driven |
| Resilience Patterns | references/patterns.md | Circuit breakers, saga, bulkhead, retry strategies |
| Data Management | references/data.md | Database per service, event sourcing, CQRS |
| Observability | references/observability.md | Distributed tracing, correlation IDs, metrics |
const { v4: uuidv4 } = require('uuid');
function correlationMiddleware(req, res, next) {
req.correlationId = req.headers['x-correlation-id'] || uuidv4();
res.setHeader('x-correlation-id', req.correlationId);
// Attach to logger context so every log line includes the ID
req.log = logger.child({ correlationId: req.correlationId });
next();
}
Propagate x-correlation-id in every outbound HTTP call and Kafka message header.
pybreaker)import pybreaker
# Opens after 5 failures; resets after 30 s in half-open state
breaker = pybreaker.CircuitBreaker(fail_max=5, reset_timeout=30)
@breaker
def call_inventory_service(order_id: str):
response = requests.get(f"{INVENTORY_URL}/stock/{order_id}", timeout=2)
response.raise_for_status()
return response.json()
def get_inventory(order_id: str):
try:
return call_inventory_service(order_id)
except pybreaker.CircuitBreakerError:
return {"status": "unavailable", "fallback": True}
// Each step defines execute() and compensate() so rollback is automatic.
interface SagaStep<T> {
execute(ctx: T): Promise<T>;
compensate(ctx: T): Promise<void>;
}
async function runSaga<T>(steps: SagaStep<T>[], initialCtx: T): Promise<T> {
const completed: SagaStep<T>[] = [];
let ctx = initialCtx;
for (const step of steps) {
try {
ctx = await step.execute(ctx);
completed.push(step);
} catch (err) {
for (const done of completed.reverse()) {
await done.compensate(ctx).catch(console.error);
}
throw err;
}
}
return ctx;
}
// Usage: order creation saga
const orderSaga = [reserveInventoryStep, chargePaymentStep, scheduleShipmentStep];
await runSaga(orderSaga, { orderId, customerId, items });
async function handleOrderEventMessage(message) {
const { type, payload, correlationId } = message;
logger.info({ correlationId }, `Processing ${type}`);
try {
if (type === 'OrderCreated') {
await reserveInventory(payload.orderId, payload.items);
} else if (type === 'PaymentProcessed') {
await scheduleShipment(payload.orderId);
}
await acknowledgeMessage(message);
} catch (err) {
logger.error({ correlationId, err }, 'Event processing failed');
// Nack for retry or DLQ routing
}
}
Service documentation (JSDoc / Javadoc):
/**
* OrderService
*
* API Contract:
* - POST /orders — create order (idempotent: use order-idempotency-key header)
* - GET /orders/{id} — fetch order details
* - DELETE /orders/{id} — cancel order (calls compensation saga)
*
* Dependencies: inventory-service (gRPC), payment-service (async event), warehouse-service (REST)
* SLA: 99.5% uptime; p99 latency <200ms for GET; circuits open after 5 failures.
* Data: owns Order aggregate; eventual consistency with shipment status.
*/
lint-commands.md for eslint/flake8/checkstyle).spectral lint service-spec.yaml.hadolint to enforce security layers, minimize image size.| Wrong | Correct |
|---|---|
| Distributed monolith: all services call same DB → data coupling | Database per service: each owns its schema; async events sync state |
| Shared database: eliminates transaction boundaries | Service DB + Event Sourcing: consistent within bounded context; eventual consistency across |
| Synchronous chains: A→B→C→D blocks on failures | Async chains: A publishes event; B, C, D subscribe independently with retries |
| No circuit breaker: cascading failures when downstream breaks | Circuit breaker: fail fast, half-open probe, auto-reset after timeout |
| Chatty services: 100 calls per request, network overhead | Coarse-grained boundaries: single call returns composed data; use caching/CQRS |
MUST: Domain-driven design boundaries | Database per service | Circuit breakers | Correlation IDs | Async for cross-aggregate | Graceful degradation | Health/readiness probes
MUST NOT: Distributed monoliths | Shared DB schemas | Sync long-running calls | Skip distributed tracing | Ignore network failures | Chatty interfaces
Creates, edits, and optimizes skills for Claude Code, including drafting, evaluating with test prompts, iterating on performance, and improving skill descriptions for better triggering accuracy.
npx claudepluginhub inho-team/qe-framework --plugin qe-framework