Advanced (Actualizado: 3/6/2026)

Microservicios con Claude Code: límites, APIs, Compose y pruebas

Diseña microservicios con Claude Code: límites, contratos API, datos, Docker Compose, observabilidad, tests y rollout.

Microservicios con Claude Code: límites, APIs, Compose y pruebas

Los microservicios son una forma de diseñar una aplicación grande como servicios pequeños e independientes que colaboran mediante APIs o eventos. Claude Code ayuda cuando se usa para revisar límites de servicio, contratos API, propiedad de bases de datos, entorno local con Docker Compose, gateway, observabilidad, pruebas y checklist de despliegue.

No conviene venderlos como una mejora automática. Al dividir un sistema aparecen fallos de red, compatibilidad de APIs, consistencia eventual, correlación de logs y rollbacks más difíciles. Si el dominio todavía cambia cada semana, un monolito modular suele ser mejor punto de partida. Para completar la base, revisa desarrollo de APIs con Claude Code, Docker Compose, logging y monitoring y arquitectura orientada a eventos.

Usa referencias oficiales como anclas de revisión: Anthropic Claude Code overview, Docker Compose documentation y OpenAPI Specification 3.1. Así separas las sugerencias de Claude Code del contrato que realmente vas a operar.

Primero Los Límites

Pide a Claude Code que explique la frontera de cada servicio antes de escribir código.

Actúa como revisor de arquitectura para migrar un e-commerce a microservicios.

Contexto:
- El flujo de pedidos cambia con frecuencia.
- Inventario debe evolucionar separado por integración con almacenes.
- Pago y notificaciones no deben bloquear el catálogo.

Entrega:
1. Servicios candidatos y responsabilidades.
2. Datos que posee cada servicio.
3. APIs síncronas y eventos asíncronos.
4. Funciones que deben quedarse en el monolito por ahora.
5. Primer sprint mínimo con Docker Compose.

Reglas:
- Sin tablas compartidas.
- Sin nombres internos de tablas en APIs.
- Sin lógica de negocio en el gateway.

Como referencias oficiales, usa Microservices architecture guide, AKS microservices reference architecture y API Management gateway overview.

Contrato API Y Propiedad De Datos

El contrato debe existir antes del handler.

openapi: 3.1.0
info:
  title: Order Service API
  version: 1.0.0
paths:
  /orders:
    post:
      summary: Create an order after reserving inventory
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required: [customerId, items]
              properties:
                customerId:
                  type: string
                items:
                  type: array
                  minItems: 1
                  items:
                    type: object
                    required: [sku, quantity]
                    properties:
                      sku:
                        type: string
                      quantity:
                        type: integer
                        minimum: 1
      responses:
        "201":
          description: Order accepted
        "409":
          description: Inventory could not be reserved
ServicioPoseePuede llamarNo debe hacer
gatewayningún dato de negocioorder, inventorycalcular stock o descuentos
order-serviceorders, order_itemsinventory API, order-eventsleer tablas de inventario
inventory-servicestock, reservationsninguno al inicioleer tablas de pedidos
notification-servicedelivery logsorder-eventscambiar estado de pedidos

Si una pantalla necesita pedidos e inventario juntos, no hagas JOIN entre bases de servicios. Usa composición de APIs, modelos de lectura, índices de búsqueda o caché alimentada por eventos.

Para las revisiones, guarda un service-inventory.json pequeño en el repositorio. Las personas deciden los límites; Claude Code verifica si un cambio los rompe.

{
  "services": [
    {
      "name": "gateway",
      "owns": [],
      "mayCall": ["order-service", "inventory-service"],
      "mustNot": ["store business data", "calculate discounts"]
    },
    {
      "name": "order-service",
      "owns": ["orders", "order_items"],
      "mayCall": ["inventory-service"],
      "mustNot": ["read inventory tables directly"]
    },
    {
      "name": "inventory-service",
      "owns": ["stock", "reservations"],
      "mayCall": [],
      "mustNot": ["change order status"]
    }
  ],
  "releaseRules": [
    "no shared database tables",
    "public APIs hide internal table names",
    "every service has healthcheck, logs, tests, and rollback notes"
  ]
}

Ejemplo Local Ejecutable

mkdir microservices-demo
cd microservices-demo
mkdir services
npm init -y
npm pkg set type=module
npm install express zod pino redis undici

compose.yaml:

services:
  gateway:
    image: node:22-alpine
    working_dir: /workspace
    command: node services/service.mjs
    environment:
      SERVICE: gateway
      PORT: 3000
      ORDER_URL: http://order-service:3000
      INVENTORY_URL: http://inventory-service:3000
    ports:
      - "8080:3000"
    volumes:
      - .:/workspace
    depends_on:
      - order-service
      - inventory-service
  order-service:
    image: node:22-alpine
    working_dir: /workspace
    command: node services/service.mjs
    environment:
      SERVICE: order
      PORT: 3000
      INVENTORY_URL: http://inventory-service:3000
      REDIS_URL: redis://redis:6379
    volumes:
      - .:/workspace
    depends_on:
      redis:
        condition: service_healthy
      inventory-service:
        condition: service_started
  inventory-service:
    image: node:22-alpine
    working_dir: /workspace
    command: node services/service.mjs
    environment:
      SERVICE: inventory
      PORT: 3000
    volumes:
      - .:/workspace
  redis:
    image: redis:7-alpine
    healthcheck:
      test: ["CMD", "redis-cli", "ping"]
      interval: 5s
      timeout: 3s
      retries: 10

services/service.mjs:

import express from "express";
import pino from "pino";
import { createClient } from "redis";
import { request } from "undici";
import { z } from "zod";
import { randomUUID } from "node:crypto";

const service = process.env.SERVICE ?? "inventory";
const port = Number(process.env.PORT ?? 3000);
const log = pino({ name: service });

function base(name) {
  const app = express();
  app.use(express.json());
  app.use((req, res, next) => {
    req.requestId = req.header("x-request-id") ?? randomUUID();
    res.setHeader("x-request-id", req.requestId);
    next();
  });
  app.get("/health", (_req, res) => res.json({ ok: true, service: name }));
  return app;
}

function inventory() {
  const app = base("inventory");
  const stock = new Map([["sku-1", 5], ["sku-2", 2]]);
  const Reserve = z.object({ sku: z.string().min(1), quantity: z.number().int().positive() });
  app.get("/inventory/:sku", (req, res) => res.json({ sku: req.params.sku, quantity: stock.get(req.params.sku) ?? 0 }));
  app.post("/inventory/reservations", (req, res) => {
    const parsed = Reserve.safeParse(req.body);
    if (!parsed.success) return res.status(400).json({ error: parsed.error.flatten() });
    const available = stock.get(parsed.data.sku) ?? 0;
    if (available < parsed.data.quantity) return res.status(409).json({ error: "insufficient_stock", available });
    stock.set(parsed.data.sku, available - parsed.data.quantity);
    log.info({ requestId: req.requestId, sku: parsed.data.sku }, "reserved");
    res.status(201).json({ sku: parsed.data.sku, remaining: stock.get(parsed.data.sku) });
  });
  app.listen(port, () => log.info({ port }, "inventory started"));
}

async function order() {
  const app = base("order");
  const redis = createClient({ url: process.env.REDIS_URL ?? "redis://localhost:6379" });
  await redis.connect();
  const Order = z.object({
    customerId: z.string().min(1),
    items: z.array(z.object({ sku: z.string().min(1), quantity: z.number().int().positive() })).min(1),
  });
  app.post("/orders", async (req, res) => {
    const parsed = Order.safeParse(req.body);
    if (!parsed.success) return res.status(400).json({ error: parsed.error.flatten() });
    for (const item of parsed.data.items) {
      const response = await request(`${process.env.INVENTORY_URL}/inventory/reservations`, {
        method: "POST",
        headers: { "content-type": "application/json", "x-request-id": req.requestId },
        body: JSON.stringify(item),
      });
      if (response.statusCode >= 400) return res.status(response.statusCode).json(await response.body.json());
    }
    const order = { id: randomUUID(), ...parsed.data, status: "accepted" };
    await redis.xAdd("order-events", "*", { type: "OrderAccepted", payload: JSON.stringify(order) });
    res.status(201).json(order);
  });
  app.listen(port, () => log.info({ port }, "order started"));
}

function gateway() {
  const app = base("gateway");
  async function forward(req, res, url) {
    const response = await request(url, {
      method: req.method,
      headers: { "content-type": "application/json", "x-request-id": req.requestId },
      body: req.method === "GET" ? undefined : JSON.stringify(req.body),
    });
    res.status(response.statusCode).send(await response.body.text());
  }
  app.post("/orders", (req, res) => forward(req, res, `${process.env.ORDER_URL}/orders`));
  app.get("/inventory/:sku", (req, res) => forward(req, res, `${process.env.INVENTORY_URL}/inventory/${encodeURIComponent(req.params.sku)}`));
  app.listen(port, () => log.info({ port }, "gateway started"));
}

if (service === "inventory") inventory();
else if (service === "order") await order();
else if (service === "gateway") gateway();
docker compose up
curl http://localhost:8080/inventory/sku-1
curl -X POST http://localhost:8080/orders -H "content-type: application/json" -d '{"customerId":"cust-1","items":[{"sku":"sku-1","quantity":2}]}'
docker compose down

Criterios Antes De Produccion

Antes de lanzar, no cuentes servicios: cuenta responsabilidades verificables. Cada microservicio debe tener propietario de datos, contrato API versionado, prueba de contrato, endpoint de salud y plan de rollback. Pide a Claude Code convertir un flujo de negocio en una tabla con estos puntos.

Observabilidad, Pruebas Y Rollout

Incluye x-request-id, logs estructurados, nombre de servicio, IDs de negocio, /health, tasa de errores y latencia desde el primer sprint. Pide a Claude Code revisar compatibilidad API, ownership de migraciones, ausencia de lógica de negocio en gateway, rutas 400/409/500, caída de Redis, feature flags, canary y rollback.

Buenos casos de uso: e-commerce con pedidos, inventario, pagos y notificaciones; SaaS B2B con facturación, permisos y auditoría; plataformas de contenido con ingesta, transformación, búsqueda y entrega. Errores típicos: dividir por tablas, compartir base de datos, crear una librería de dominio común enorme, meter reglas en el gateway y desplegar sin observabilidad.

En términos prácticos, un buen use case no es “queremos arquitectura moderna”, sino “esta capacidad cambia, escala o falla de forma distinta al resto del producto”. Un pitfall frecuente es generar muchos repositorios sin ownership real. Pide a Claude Code una ficha por servicio candidato: propietario, contrato API, tablas que posee, eventos publicados, eventos consumidos, dashboard, SLO, comando de deploy, comando de rollback y comportamiento cuando una dependencia falla.

También conviene incluir la ruta de negocio. Si el servicio toca checkout, alta de trial, emails, anuncios, reportes o formularios de consulta, el checklist debe decir cómo se valida esa conversión. Una división técnicamente limpia que rompe atribución, notificaciones o seguimiento de ingresos sigue siendo mala ingeniería. Para el primer PR, suele ser mejor crear inventario y pruebas de contrato que abrir diez carpetas nuevas.

Si necesitas snippets de CLAUDE.md, checklists de review y plantillas de contrato API para reutilizar, empieza por los productos prácticos de ClaudeCodeLab.

Para revisar límites, contratos API, Compose y monitoreo en un proyecto real, puedes empezar con Claude Code training and consultation sobre un único flujo de negocio.

#Claude Code #microservicios #API design #Docker Compose #observabilidad #testing
Gratis

PDF gratis: cheatsheet de Claude Code

Introduce tu email y descarga una hoja con comandos, hábitos de revisión y flujos seguros.

Cuidamos tus datos y no enviamos spam.

Masa

Sobre el autor

Masa

Ingeniero enfocado en workflows prácticos con Claude Code.