AKAkki
Back to all articles
Full-Stack Architecture•6 min read

Architecting a Real-Time POS with Next.js Server Actions and Optimistic UI

How to build low-latency retail and salon point-of-sale systems that handle rapid barcode scans, cart edits, and split-payment transactions without screen flashes.

AK

Akki

Full-Stack Developer

Building software for physical retail counters requires a radically different mindset than designing standard SaaS products. When a customer is waiting at the counter to settle a bill, every 200 millisecond delay feels like an eternity.

The Latency Challenge at the Front Desk

In my work on SalonOS (a salon management and POS platform), the primary requirement was clear: the receptionist must be able to tap services, assign stylists, add discounts, and collect payment within seconds. If the application requires a loading spinner for each cart item, receptionists quickly revert to paper logs.

Decoupling Local Cart State from Server Roundtrips

Rather than submitting every service addition over the wire sequentially, we maintain the operational cart state locally using React state hooks with optimistic updates. The cart recalculates itemized line items, tax brackets, and stylist commission splits synchronously in memory.

Transactional Server Actions with Prisma

When the cashier clicks "Complete Checkout", the client dispatches a validated payload to a Next.js Server Action. This action wraps the entire checkout within an atomic database transaction:

typescriptSnippet
export async function completeCheckout(orderPayload: CheckoutInput) {
  return await prisma.$transaction(async (tx) => {
    // 1. Verify item availability and stylist assignment
    const stylist = await tx.staff.findUniqueOrThrow({
      where: { id: orderPayload.stylistId },

// 2. Generate invoice record const invoice = await tx.invoice.create({ data: { totalAmount: orderPayload.finalTotal, paymentMode: orderPayload.paymentMode, status: "COMPLETED", items: { create: orderPayload.items.map(item => ({ serviceId: item.id, price: item.price, stylistCommission: item.price * stylist.commissionRate, })) } } });

return invoice; }); } ```

If any constraint fails—such as an invalid stylist ID or invalid payment mode—the entire transaction cleanly rolls back.

Browser Thermal Printing Without Third-Party Drivers

For receipts, instead of forcing the salon to install proprietary desktop driver utilities, we format a clean CSS print stylesheet constrained to 80mm thermal paper widths. Using `window.print()` targeted to an isolated DOM ref generates an instantaneous thermal slip directly from standard USB or Bluetooth ESC/POS printers.

Engineering Takeaways for Business Apps

1. **Local state first:** Never let the network block counter interactions. 2. **Atomic transactions:** Wrap multi-entity checkouts in relational database transactions. 3. **Keep hardware integrations simple:** Native browser APIs (like print stylesheets) frequently outlast bloated desktop helper apps.

Topics & Tags
#Next.js#React#TypeScript#Prisma#PostgreSQL

Need technical leadership or architecture for your next project?

Let's discuss your engineering requirements and build a maintainable solution.