operacoes
Um único estoque para seis canais: onde quebra de verdade
Vender em web + Telegram + ChatGPT + WhatsApp + voz com um pool único de estoque parece simples. Quebra sempre igual.
O sonho é: uma tabela de produtos, seis superfícies de venda, e o estoque «simplesmente funciona». O problema real é a unidade de consistência, não as superfícies.
A race condition que toda loja multi-canal pega
Dois clientes, dois canais, última unidade.
- 00:00.000 — Cliente A no site abre a PDP. Servidor lê
stock = 1. - 00:00.040 — Cliente B no Telegram pergunta "ainda tem?". Bot lê
stock = 1. Responde "sim". - 00:00.180 — A clica Comprar.
- 00:00.220 — B diz "fico com ele". Bot chama
add_to_cart. - 00:00.310 — Checkout do A escreve
stock -= 1(agora 0). - 00:00.350 — Checkout do B escreve
stock -= 1(agora -1).
Você tem overselling e um deles vai receber email de desculpas.
O que funciona: lock pessimista na linha do SKU
Cada add-to-cart ou checkout que quer consumir estoque pega um row-level lock na linha do SKU, lê dentro do lock, decide, escreve, libera. O site bloqueia 50ms enquanto o bot termina; o segundo vê a verdade e recusa. Ambos clientes recebem a resposta certa.
Em Prisma:
await prisma.$transaction(async (tx) => {
const product = await tx.product.findUnique({ where: { id }, select: { stock: true, trackStock: true } });
if (product?.trackStock && product.stock < qty) throw new Error("OUT_OF_STOCK");
await tx.product.update({ where: { id }, data: { stock: { decrement: qty } } });
});
SQLite serializa por file-lock; Postgres por row-lock; em qualquer caso a segunda transação espera o commit da primeira.
O que não funciona: caches
Réplicas de leitura, caches Redis, contadores denormalizados por canal — tudo ganha latência na leitura e perde correção na escrita. A escrita do estoque tem que ser autoritativa; leituras podem cachear, mas o cache precisa ser invalidado sincronamente em cada escrita, senão mente para o próximo canal.
O que quebra com reservas
Muitas plataformas tentam "reservar" estoque ao iniciar o carrinho e "comitar" no checkout. Funciona até o carrinho ser abandonado e ninguém limpar a reserva. Três meses depois, seu estoque autoritativo e o exibido divergem em 40%. Cura é TTL na reserva: após N minutos de inatividade, libera automático.
O que os canais AI adicionam
Cada canal AI (ChatGPT, Telegram, voz) é um tool consumer falando com sua loja. Superfície de race-condition multiplica, mas a cura não muda. Tool-calls vão para o mesmo decremento atômico. O AI não sabe que está numa corrida; o banco sabe.
Lojistas que nunca têm overselling tratam estoque como conta bancária: cada saque trava primeiro, lê dentro do lock, decide, escreve. Chato, rápido, correto.