Skip to content
All projects
Case studyCS/05
StatusPersonal project
TypeSystems
Year2026

SwiftKart

The engine behind 10-minute grocery delivery

Dark-store inventory that never oversells, an order saga that survives failures, and rider dispatch with batching, all on a live map. Customers see what the nearest store has right now and get an honest ETA; operations get a city map, on-time rate and a flash-sale lab that proves the platform doesn't oversell.

  • 300 buyers, 50 units, 0 refunds
  • 86% on time
  • Atomic cart reservation
  • Fenced leader lease

§1

The problem

Quick commerce runs on thin margins. When 300 people tap Buy for 50 units, check-then-decrement code takes everyone's money and refunds most of them. A '10 minutes' promise that ignores the picking queue becomes a late order, and riders are the biggest cost.

§2

My role

Personal project, end to end: the inventory, order and dispatch services, the saga and reconciler, rider assignment and batching, the React store and ops console with a live map, and Kubernetes manifests.

§3

Architecture

Fig. 1 · SwiftKart architecture
reserveoutboxledgerSTORE + OPSReact · LeafletGATEWAYJWT · rate limitsORDER-SERVICEsaga · outboxINVENTORY-SERVICELua reserveDISPATCH-SERVICEGEO · batchingKAFKAorder eventsREDISstock · GEO · leasePOSTGRESledger · orders
clientserviceeventdata

§4

Key decisions

  1. D/01

    A whole cart in one Lua script

    Check-and-decrement for every line is atomic, with Redis Cluster hash tags so a store's keys share a slot. Postgres stays the ledger and can never go negative, even if Redis is wrong.

  2. D/02

    Orchestrated saga with an outbox

    One service owns the order state machine; reservations expire after 120 s through a sorted set any replica can sweep, and status only moves forward with optimistic locking.

  3. D/03

    Honest delivery promises

    Promise = picking + queue ahead + handover + ride, with the clock starting at payment. Queue position comes from an atomic per-store Redis gauge, not a database count.

  4. D/04

    Dispatch on a GEO index

    Rider candidates come from a Redis GEO radius query, scored by time-to-store minus a fairness bonus for idle time. Two drops within 1.2 km and a 4-minute detour share one trip.

  5. D/05

    One leader for the fleet

    A fenced Redis lease with compare-and-extend renewal makes exactly one dispatch replica move riders, and fleet state is snapshotted so a new leader resumes seamlessly.

§5

Challenges

  • The flash-sale lab: the atomic path told exactly 50 of 300 buyers 'reserved' with 0 refunds every run; the naive path told 174–300 and refunded 124–250. The ledger still refused to go negative, and the reconciler repaired the phantom stock.
  • During a flash sale 50 checkouts in the same second each saw an empty queue and were promised 7 minutes (actual: 25). Joining a sorted set now returns each buyer's true position, so promises range from 7 to 25 minutes.
  • The first flash sale after a deploy timed out on cold paths, and 300 simultaneous connections overflowed Tomcat's default backlog of 100. Services now warm up and size the accept queue for bursts.
  • Kafka events arrive out of order (a rider assigned while still packing), so late events can't move an order backwards, and processed_events gives exactly-once effects.

§6

Stack

  • Java 21
  • Spring Boot 4
  • Spring Cloud Gateway
  • Kafka
  • Redis (Lua, GEO, pub/sub)
  • PostgreSQL
  • React
  • Leaflet
  • Kubernetes

Next case study

TorrentShare

Peer-assisted artifact distribution for GPU fleets and MLOps pipelines