A las 9:00 empieza la oferta. La CDN mantiene en pie las páginas de producto, pero el checkout falla: dos compradores se llevan la última unidad de la misma chaqueta, un reintento tras un timeout deja dos retenciones de pago en una tarjeta, y el almacén se entera de un pedido con una hora de retraso porque se perdió un evento.
Ninguno de estos es un problema de capacidad. Son problemas de límites: quién es dueño de qué datos y qué pasos deben terminar mientras el comprador espera.
Este artículo recorre una arquitectura e-commerce realista para una tienda mediana: componentes y propiedad de los datos, el camino de checkout paso a paso, el flujo de pedidos posterior, el tráfico pico y un diagrama de la plataforma.
Parte de lo que hacen los compradores
Cinco recorridos cubren la mayor parte de lo que hace una tienda, con exigencias muy distintas:
| Recorrido | Componentes en el camino | Qué puede estar desactualizado |
|---|---|---|
| Navegar | CDN, gateway, Catalog | Precios y stock de una página en caché, durante minutos |
| Buscar | Índice de búsqueda | Productos modificados, durante segundos |
| Carrito | Cart | Nada de lo que el comprador acaba de cambiar |
| Checkout | Checkout, Inventory, proveedor de pagos, Orders | Nada |
| Seguir el pedido | Orders, Fulfillment | Estado del envío, durante minutos |
Navegar y buscar llevan la mayoría de las peticiones y toleran datos desactualizados; el checkout lleva pocas y no tolera ninguno. Gran parte de la arquitectura se deriva de esa división.
Los componentes y los datos que posee cada uno
En el borde, una CDN cachea páginas e imágenes, y una puerta de enlace de API (o un backend for frontend por tipo de cliente) autentica, limita la tasa y enruta el resto. Cada servicio detrás es dueño de sus datos:
| Servicio | Posee | Almacén típico | Necesidad de consistencia |
|---|---|---|---|
| Catalog | Productos, variantes, precios | Postgres, lectura a través de cachés | Eventual; checkout vuelve a leer los precios |
| Search | Índice de productos con facetas | OpenSearch o Elasticsearch | Eventual, actualizada desde los cambios del catálogo |
| Cart | Líneas de carrito por comprador | Redis con TTL | Read-your-writes por comprador |
| Checkout | Sesiones: totales, ID de reserva y de pago | Postgres | Fuerte dentro de una sesión |
| Inventory | Stock por SKU, reservas | Postgres | Fuerte: nunca vender de más |
| Orders | Pedidos, historial de estados, outbox | Postgres | Fuerte: un solo writer por pedido |
| Proveedor de servicios de pago (PSP) | Autorizaciones, capturas, reembolsos | El PSP | Manda el registro del PSP |
| Fulfillment | Envíos, números de seguimiento | WMS o 3PL | Eventual, guiada por eventos |
Los demás servicios usan la API o los eventos del propietario, nunca sus tablas. El stock y los pedidos necesitan transacciones; los carritos y el índice de búsqueda pueden retrasarse, o incluso perder una escritura, sin un daño real.
El camino de checkout, paso a paso
El checkout es el único flujo en el que el comprador espera a varios servicios a la vez:
Recalcula el precio del carrito. Checkout lee el carrito, obtiene los precios actuales del catálogo y calcula impuestos, envío y descuentos en el servidor. Nunca confíes en el total de un navegador.
Reserva stock con caducidad, aquí 15 minutos:
-- One transaction: take the stock, then record the hold UPDATE stock SET reserved = reserved + 2 WHERE sku = 'JKT-042-M' AND on_hand - reserved >= 2; -- 0 rows: out of stock, stop INSERT INTO reservations (checkout_id, sku, qty, expires_at) VALUES ('chk_41a', 'JKT-042-M', 2, now() + interval '15 minutes');Cuando dos compradores compiten por la última chaqueta, el nivel de aislamiento por defecto de PostgreSQL, Read Committed, hace esperar al segundo update y vuelve a comprobar su cláusula WHERE contra la fila nueva, así que uno obtiene cero filas. Un sweeper devuelve al stock las retenciones caducadas. Con una página de pago alojada, alinea los relojes: las sesiones de Stripe Checkout duran 24 horas salvo que fijes una caducidad más corta (30 minutos como mínimo) o las expires tú mismo;
checkout.session.expiredte avisa de que debes liberar los artículos.Crea el pago con una clave de idempotencia. Checkout pide al PSP un pago por el total calculado en el servidor, con captura manual y una clave de idempotencia guardada antes de la llamada. Tras un timeout, reintenta con la misma clave: Stripe devuelve la respuesta guardada en lugar de crear un segundo pago. Sus claves tienen hasta 255 caracteres y pueden eliminarse pasadas 24 horas.
Autoriza. Amplía primero la reserva de stock, para que no caduque a mitad del pago. El comprador escribe los datos de la tarjeta en los campos del PSP, así que los números de tarjeta nunca llegan a tus servidores, y el emisor puede pedir 3-D Secure. Si sale bien, los fondos quedan retenidos: un pago de Stripe con captura manual pasa a
requires_capturey emitepayment_intent.amount_capturable_updated. Confía en ese webhook, no en la redirección del navegador; consulta el diagrama de integración de una pasarela de pago.Crea el pedido. Orders crea el pedido como
placedy escribeOrderPlaceden una tabla outbox en la misma transacción. Después, Checkout indica a Inventory que convierta la reserva en una asignación.Captura al enviar. Cuando Fulfillment envía, Orders captura. En el momento de escribir esto (noviembre de 2026), Stripe documenta que las autorizaciones de tarjeta online suelen durar 7 días, o 5 días (exactamente 4 días y 18 horas) para las transacciones de Visa iniciadas por el comercio; luego los fondos se liberan y el pago se cancela. La mayoría de los pagos con tarjeta permiten una sola captura, y una captura parcial libera el resto.
Si un paso falla antes de que exista el pedido, deshaz los anteriores en orden inverso: cancela la autorización, libera la retención. Es una saga con el checkout como orquestador.
Dónde cambian el dinero, el stock y el estado del pedido
| Estado del pedido | Se establece cuando | Pago | Stock |
|---|---|---|---|
| Checkout abierto | Se reserva el stock | Creado, no autorizado | Retenido 15 minutos |
| Placed | El PSP informa de la autorización | Fondos retenidos | Asignado al pedido |
| Shipped | Fulfillment envía | Capturado | Descontado del stock disponible |
| Canceled | Cancelado antes del envío | Autorización cancelada | Liberado |
| Returned | Se recibe la devolución | Reembolsado | Repuesto tras la inspección |
Los casos difíciles están entre las filas. Si una autorización llega después de que caduque la retención, vuelve a reservar si queda stock; si no, cancela la autorización e informa al comprador. Si un pedido pendiente de stock supera la ventana de 7 días, captura el importe completo en el primer envío, usa una autorización extendida donde tu PSP la ofrezca (hasta 30 días en algunas redes de tarjetas, según Stripe) o cobra por adelantado y reembolsa lo que no puedas enviar. Algunos métodos de pago, como ACH e iDEAL, no pueden capturar por separado en absoluto.
Después de crear el pedido
Todo lo que sigue a placed se ejecuta de forma asíncrona. Un relay publica OrderPlaced desde el outbox en el topic order-events, de modo que no se pierde ningún evento entre el commit y el broker (consulta el patrón transactional outbox). Fulfillment prepara, empaqueta y envía, y luego publica OrderShipped, que dispara la captura. Notifications envía los correos; Analytics carga cada evento en el almacén de datos.
La entrega es al menos una vez, así que los consumidores deduplican por ID de evento. Usar el ID de pedido como clave del topic mantiene en orden los eventos de cada pedido.
El diagrama de arquitectura de microservicios cobra la tarjeta después de OrderPlaced. Eso encaja con pagos sin interacción del comprador; 3-D Secure necesita al comprador presente, así que este diseño autoriza dentro del checkout.
Sobrevivir al tráfico pico
Supón una hora de oferta con 7 200 pedidos, una tasa de conversión del 2 % y 10 páginas vistas por sesión: 360 000 sesiones y 3,6 millones de páginas vistas, es decir, unas 1 000 páginas vistas por segundo frente a 2 pedidos por segundo. Cada mitad necesita su propia protección:
- Cachea el catálogo en el borde. Con
Cache-Control: public, max-age=0, s-maxage=300, stale-while-revalidate=60, la CDN sirve una página de producto durante cinco minutos y luego hasta un minuto más mientras la vuelve a pedir en segundo plano, tal como define la RFC 5861. Con un 90 % de aciertos, el origen ve 100 páginas vistas por segundo en lugar de 1 000. Purga al cambiar precios; checkout vuelve a comprobar de todos modos. - Pon una cola delante del checkout. Una sala de espera virtual admite compradores a un ritmo que Inventory y el PSP puedan sostener, como en el diseño de un sistema de reserva de entradas.
- Protege los SKU calientes. Las reservas de un SKU actualizan una fila, una a la vez. Con 2 ms de tiempo de bloqueo por transacción, esa fila llega a un máximo de unas 500 reservas por segundo. Mantén la transacción corta y sin llamadas al PSP, reparte el stock de un artículo estrella en varias filas y limita la cantidad por pedido.
- Conoce los límites de tasa de tu PSP antes de la oferta.
Empieza más pequeño que esto
Muchas tiendas no deberían construir todo esto. Una plataforma alojada como Shopify o BigCommerce ejecuta catálogo, carrito y checkout por ti; tu diagrama entonces muestra las apps y los webhooks a su alrededor.
Un desarrollo a medida suele empezar mejor como monolito modular: los mismos límites como módulos en un único desplegable. En 2019, los ingenieros de Shopify describieron cómo reorganizaron una de las mayores bases de código de Ruby on Rails en torno a pedidos, envíos, inventario y facturación, en lugar de dividirla en microservicios. Extrae un servicio cuando un módulo necesite su propia escala o sus propias versiones; el diagrama sigue valiendo.
El diagrama de la plataforma e-commerce
Contenido del diagrama
- Shopper
- CDN
- API gateway / BFF
- Catalog
- Search
- Cart
- Checkout
- Orders
- Inventory
- Payment provider (PSP)
- order-events
- Fulfillment
- Notifications
- Analytics warehouse
- HTTPS
- misses, API
- GET /products
- GET /search
- POST /cart/items
- POST /checkout
- GET /orders/{id}
- product changes
- read cart
- reserve, 15 min
- authorize + idempotency key
- place order
- capture on OrderShipped
- OrderPlaced
- placed, shipped
- all events
Cómo leerlo:
- Las peticiones entran arriba a la izquierda: comprador, CDN y luego el gateway, que enruta cada recorrido a un servicio.
- El azul es el camino de navegación. La arista discontinua es el índice de búsqueda poniéndose al día con los cambios de producto.
- El ámbar es el camino de checkout, donde el comprador espera: leer el carrito, reservar stock, autorizar y crear el pedido.
- El proveedor de pagos recibe dos llamadas: autorizar durante el checkout y capturar con
OrderShipped(turquesa discontinua). - Las aristas violetas discontinuas son eventos, del outbox a través de order-events hasta Fulfillment, Notifications y Analytics.
- Cada servicio nombra su almacén, y el bloque Markdown enumera las cifras.
Dibujar con claridad diagramas de arquitectura e-commerce
- Etiqueta las aristas del gateway con rutas como
GET /products, para que los lectores relacionen páginas con servicios. - Nombra el almacén en cada servicio. Una base de datos compartida no debería pasar desapercibida.
- Continua para esperar, discontinua para después. Las llamadas que el comprador espera deben verse distintas de los eventos.
- Escribe los tiempos en las aristas. La duración de la retención y el disparador de la captura son lo que más revisión necesita.
- Dibuja la autorización y la captura como dos aristas. Una sola flecha al PSP oculta el momento clave.
- Deja fuera pods, regiones, proveedores de impuestos y antifraude, y el back office.
Constrúyelo en Archboard
- Inicia sesión con Google o GitHub y crea un diagrama.
- Añade una Persona del paquete C4 Model, y debajo una CDN y una Puerta de enlace de API del paquete Nube.
- Añade cinco nodos Contenedor del paquete C4 Model en una columna: Catalog, Search, Cart, Checkout y Orders, cada uno con su almacén en la descripción.
- Añade un Contenedor para Inventory, un Sistema externo para el proveedor de pagos y un Tema del paquete Datos para order-events. A su derecha, añade nodos Contenedor para Fulfillment y Notifications y un Almacén de datos del paquete Datos.
- Conecta el gateway con los cinco servicios con etiquetas de ruta. Haz continuas las llamadas del checkout y discontinuos los cambios de producto, la captura y los eventos.
- Añade un bloque Markdown del paquete Básico con las cifras, y notas de Texto para la leyenda y las reglas clave.
Si tus servicios se ejecutan desde un archivo Compose, la herramienta Docker Compose a diagrama esboza las cajas; la plantilla de arquitectura de microservicios es otro punto de partida. El ejemplo usa 15 nodos de diagrama, dentro del plan Free.
Preguntas frecuentes
¿Cuáles son los componentes principales de una arquitectura e-commerce? Una CDN, una puerta de enlace de API, servicios de catálogo, búsqueda, carrito, checkout, inventario y pedidos, un proveedor de pagos, y Fulfillment, Notifications y Analytics. Las plataformas alojadas agrupan la mayoría.
¿Debería una tienda online usar microservicios? No por defecto. Un monolito modular con los mismos límites es más sencillo de operar, y Shopify eligió uno para su núcleo. Extrae un servicio cuando un módulo necesite escala o versiones independientes.
¿Cómo se evita vender inventario de más? Reserva stock con un update atómico y condicional por SKU, dale caducidad a cada reserva y asígnala solo cuando se cree el pedido. Nunca decidas la disponibilidad a partir de una página en caché.
¿Cuándo debería una tienda online capturar el pago? Para bienes físicos, normalmente al enviar, para cobrar solo lo que se envía. Las autorizaciones de tarjeta online suelen durar 7 días. En Stripe, Klarna permite 28 días y PayPal 10, que Stripe intenta ampliar a 20.
¿Cómo gestionan los sitios e-commerce los picos de tráfico? Sirven el catálogo desde la CDN, ponen a los compradores en cola delante del checkout y protegen los SKU calientes y al proveedor de pagos. Planifica la capacidad del checkout por separado de las páginas vistas.