Skip to content
→ All work

Case study 03 / 26

Kinamna

A multi-vendor marketplace for Nepal: storefront, seller portal and superadmin console on one 183-endpoint API, with tamper-proof Khalti, eSewa and Fonepay payments.

Status
Deployed
Domain
web · cloud · security
Source of claims
Private repository README (reviewed). Source and deployment are not public.

Customers shop, sellers run their own catalogue, stock and orders, and platform staff oversee every business — three portals on one FastAPI backend whose boundaries are enforced in the API, not the browser. The backend was migrated from Express + Prisma to FastAPI + SQLAlchemy without changing the schema, URLs, JSON shapes or issued tokens.

01/The problem

A marketplace handles other people's money and other businesses' data. A seller must never see a competitor's orders, a customer must never be able to set their own price, and a payment callback replayed or tampered with must never confirm an order twice — or at all.

02/The system

Customers shop, sellers run their own catalogue, stock and orders, and platform staff oversee every business — three portals on one FastAPI backend whose boundaries are enforced in the API, not the browser. The backend was migrated from Express + Prisma to FastAPI + SQLAlchemy without changing the schema, URLs, JSON shapes or issued tokens.

03/Scope

  1. 01Three portals — storefront, business portal and superadmin console — on one API of 183 endpoints with generated OpenAPI docs.
  2. 02Roles for customers, store managers, support and admins; business and superadmin guards re-read the account on every request, so suspension takes effect immediately.
  3. 03Khalti, eSewa, Fonepay, card and cash-on-delivery payments, plus superadmin refunds recorded only after the gateway confirms them.
  4. 04Business approval lifecycle (pending → approved → suspended…) and an audit log of status changes and refunds.
  5. 05Catalogue with variants and options, carts, wishlists, waitlists, reviews with seller replies, sales and promotions; direct-to-R2 uploads via presigned URLs.
  6. 06Running on Kubernetes with Neon Postgres behind an nginx ingress; non-root containers, health probes and graceful drain.

04/Engineering

The browser never sets the price

Amounts are recomputed from stored line items and cross-checked against the order total; the browser's payment status is ignored and a server-side gateway lookup is the only source of truth. A short payment is never accepted as success.

Settle exactly once

Settlement is a single conditional update behind a state machine that rejects backwards transitions, so duplicate and replayed callbacks are no-ops — no double stock decrement, no second confirmation email.

Isolation resolved from the database

Every business query filters on a store id the guard resolved from the authenticated user — never one from the URL or body — and another store's product answers 404, so ids can't be probed.

A backend swap nobody noticed

The Express + Prisma API was replaced with FastAPI + SQLAlchemy against the same schema, URLs, JSON and JWTs; Alembic autogenerate against the live schema produces an empty migration.

05/Interface

Interface screenshots of this commercial product are not public. The visual above is an abstract representation of its modules — not the product itself.

06/Tech stack

  • FastAPI
  • Python 3.13
  • SQLAlchemy
  • Alembic
  • Next.js 14
  • React 18
  • TanStack Query
  • PostgreSQL (Neon)
  • Redis
  • Kubernetes
  • Cloudflare R2

07/Result

Verified outcomes

  • Running in production on Kubernetes with Neon PostgreSQL.
  • 126 tests against a real PostgreSQL schema covering payments, replays, refunds, RBAC, business isolation and customer flows.

08/Links

Private commercial codebase — no public links.

Next case study

DataUdaan →