Real World Example

Placing an Order in a Transaction

When thousands of people buy during a Flipkart Big Billion Days sale, stock must never go below zero and an order must never be half-saved. Use a database transaction with a conditional stock update:

// lib/dal/checkout.ts
import 'server-only';
import { prisma } from '@/lib/prisma';
import { verifySession } from './orders';

export async function placeOrder(items: { productId: number; qty: number }[]) {
  const user = await verifySession();

  return prisma.$transaction(async (tx) => {
    let totalPaise = 0;
    for (const item of items) {
      // decrement only if enough stock: atomic in PostgreSQL
      const updated = await tx.product.updateMany({
        where: { id: item.productId, stock: { gte: item.qty } },
        data: { stock: { decrement: item.qty } },
      });
      if (updated.count === 0) throw new Error('OUT_OF_STOCK:' + item.productId);
      const p = await tx.product.findUniqueOrThrow({ where: { id: item.productId }, select: { price: true } });
      totalPaise += Math.round(Number(p.price) * 100) * item.qty;
    }
    return tx.order.create({
      data: { userId: user.id, status: 'PENDING_PAYMENT', totalPaise, items: { create: items } },
      select: { id: true, totalPaise: true },
    });
  });
}

Why the Conditional Update

Example

Two buyers race for the last unit. "Read, then write" oversells; a conditional update does not:

type Product = { id: number; stock: number };

async function readThenWrite(p: Product, buyer: string) {
  const stock = p.stock;              // both read 1
  await Promise.resolve();            // the other request runs here
  if (stock >= 1) { p.stock = stock - 1; return buyer + ' bought'; }
  return buyer + ' sold out';
}

async function conditionalUpdate(p: Product, buyer: string) {
  await Promise.resolve();
  if (p.stock >= 1) { p.stock -= 1; return buyer + ' bought'; } // like UPDATE ... WHERE stock >= 1
  return buyer + ' sold out';
}

async function main() {
  const a = { id: 1, stock: 1 };
  console.log(await Promise.all([readThenWrite(a, 'Ravi'), readThenWrite(a, 'Anita')]), 'stock =', a.stock, '(sold 2, had 1!)');
  const b = { id: 1, stock: 1 };
  console.log(await Promise.all([conditionalUpdate(b, 'Ravi'), conditionalUpdate(b, 'Anita')]), 'stock =', b.stock);
}
main();

Output

[ 'Ravi bought', 'Anita bought' ] stock = 0 (sold 2, had 1!)
[ 'Ravi bought', 'Anita sold out' ] stock = 0