Adios
BlogComercio electrónico con Next.js

Comercio electrónico con Next.js

Cómo gestionar inventario e invalidación de caché en una tienda Next.js

Evita vender más unidades de las disponibles con inventario transaccional, reservas, webhooks idempotentes, etiquetas de caché Next.js, invalidación específica y pruebas de concurrencia.

Equipo de AdiosActualizado 17 de julio de 20268 min de lectura

El inventario es una transacción, no un valor de caché. La caché puede indicar al comprador qué había disponible recientemente; solo la escritura en la fuente de referencia puede prometer la última unidad.

Define disponible, reservado y vendido

Trail Supply tiene dos Alpine Shell azules de talla mediana. onHand es el recuento físico, reserved es el stock reservado temporalmente por intentos activos de pago y sold corresponde a pedidos confirmados. Available se deriva de esos estados persistentes, en lugar de guardarse como un número independiente que pueda desajustarse.

Define cuándo empieza una reserva, cuánto dura y qué evento la confirma o libera. Reservar al añadir al carrito suele ser demasiado pronto; reservar en Checkout puede encajar con inventario limitado; reservar al pagar requiere una política para compradores simultáneos.

Haz atómico el cambio de stock

Una secuencia de lectura y escritura permite que dos solicitudes vean la misma última unidad. Usa una transacción de base de datos, bloqueo de fila, actualización condicional u otra operación atómica admitida por el almacén de datos. La escritura solo tiene éxito si queda suficiente stock sin reservar.

Impide cantidades negativas con restricciones de base de datos cuando sea posible. Registra reserva, variante, cantidad, propietario o pedido pendiente, hora de creación, caducidad y estado en la misma transacción que cambia la disponibilidad.

const reserved = await db.inventory.updateMany({
  where: {
    variantId,
    available: { gte: quantity },
  },
  data: {
    available: { decrement: quantity },
    reserved: { increment: quantity },
  },
});

if (reserved.count !== 1) {
  return { error: "Insufficient stock" };
}

Haz caducar las reservas de forma deliberada

Guarda una caducidad y ejecuta una tarea programada de recuperación que libere las reservas activas cuyas sesiones Checkout ya no puedan completarse. Haz idempotente la liberación: cambiar una reserva ya confirmada o liberada no debe hacer nada.

Los eventos tardíos necesitan una política. Si el pago termina después de la caducidad local, concilia con el estado del proveedor y de preparación del pedido, en lugar de recrear stock o cancelar a ciegas un pedido pagado. Algunas tiendas permiten pedidos pendientes de stock; otras reembolsan. Codifica la decisión del producto.

Guarda lecturas del catálogo en caché, no la autoridad

Con Cache Components activo, guarda en caché la presentación de productos y categorías con use cache, un cacheLife adecuado y etiquetas del producto, variante y categorías afectadas. La disponibilidad mostrada puede estar ligeramente obsoleta solo si el pago realiza una validación autorizada.

Mantén el código de mutación de carritos e inventario fuera de las cachés públicas compartidas. Los carritos específicos del usuario necesitan datos de cada solicitud o una caché privada. Nunca guardes una promesa de stock vinculada a una sesión en una clave que pueda recibir otro comprador.

export async function getProduct(slug: string) {
  "use cache";
  cacheLife("minutes");
  cacheTag("product:" + slug);
  return loadProductView(slug);
}

Invalida el menor conjunto correcto

Tras modificar stock o precio, invalida el producto y cada página de categoría que muestre el valor cambiado. updateTag permite que una Server Action lea sus propias escrituras; revalidateTag con un perfil adecuado encaja con contenido que puede servir datos obsoletos mientras se actualiza.

No borres todas las páginas de tienda en caché cuando cambie una chaqueta azul de talla mediana. La invalidación amplia aumenta la carga y dificulta entender la caché. Centraliza la creación de etiquetas para que editores, webhooks y acciones de administración identifiquen las mismas entradas.

Concilia los eventos de almacén y pago

Registra los IDs de eventos externos antes de cambiar el stock. Un ajuste de almacén, cancelación, reembolso o finalización de pago pueden repetirse o llegar fuera del orden esperado. Convierte cada uno en una transición local de inventario y rechaza las transiciones que no correspondan al estado actual.

Mantén un registro de movimientos al que solo se añadan entradas o un historial de auditoría suficiente para explicar el total. Una cantidad actual sin historial de reservas y pedidos es difícil de reparar tras un fallo de proveedor o despliegue.

Prueba la contención y la recuperación bajo carga

Envía muchas solicitudes simultáneas de reserva para las dos últimas unidades y comprueba que como máximo dos tengan éxito. Interrumpe un proceso de trabajo, repite un evento de pago, haz caducar una reserva, entrega una finalización tardía y reconstruye la vista de producto en caché. Comprueba las condiciones de la base de datos y los resultados visibles para el cliente.

Ejecuta esas pruebas contra la compilación de producción en una vista previa de Adios. Los registros del entorno de ejecución muestran errores de contención y webhooks; las dependencias de base de datos y secretos siguen explícitas en el manifiesto. Promueve cuando pasen la ruta de salud y las pruebas básicas de inventario.

Todos los artículos