Hashmato: multi-tenant cloud POS

Payment, delivery, pricing, and ordering services for a database-per-tenant POS, where every tenant brings its own providers.

Company
HashmatoCloud POS for F&B and retail operators, part of RBS’s hospitality portfolio (4,800+ properties, 35+ countries).
Role
Software Engineer II
Period
Sep 2025 – Mar 2026
Location
Singapore (remote)

Original reconstruction for this portfolio.

Overview

Hashmato is a cloud POS for food-and-beverage and retail operators. I worked on its backend: the payment gateway, the food-delivery integration service, the shared data-access layer, a pricing engine, and a stored-value ordering backend.

Every one of these runs per tenant, and each tenant can be configured differently.

Context and problem

In a multi-tenant POS, tenants don’t share a payment provider, a delivery partner, or a price list. One tenant takes Stripe, another PayNow QR. One sells on Grab, another on Deliveroo.

Money and orders also leave no room for partial failure. Webhooks can arrive more than once, partners retry, and refunds have to reconcile.

My role and ownership

What I built

  • Architected a multi-provider payment gateway: Stripe, Omise, PayNow QR, or an in-house gateway behind one adapter interface, with HMAC-verified webhooks and BullMQ retries.
  • Built a food-delivery integration service connecting POS menus and orders to Deliveroo, Grab, and Delivery Hero: menu sync, order ingestion, store status, and OAuth2/HMAC webhooks.
  • Designed the shared data-access layer behind 30+ domain modules of a database-per-tenant PostgreSQL/TypeORM platform: nested-relation filters, transactional bulk upserts, streaming export, and queued Excel import.
  • Built a context-aware pricing engine from scratch (brand, location, channel, and timezone schedules), then removed an N+1 bottleneck by batching per-item override lookups into one query per page.
  • Delivered a stored-value ordering backend: cart and combos, prepaid wallets, auto-recharge, ledgered refunds, and partial cancellations, using PostgreSQL transactions and atomic Redis Lua queue numbering.
  • Extended Kubernetes delivery for 7 NestJS microservices (Helm, helmfile, SOPS, Traefik) and containerized 3 new services with multi-stage Docker builds and GitHub Actions publishing to GHCR.

Challenges

  • Many providers, one checkout

    Each tenant can run a different payment provider, and the POS shouldn’t need to know which one.

  • Partners that speak different protocols

    Delivery platforms each have their own menu formats, order flows, store status, and webhook security.

  • Prices that depend on context

    The same item can cost different amounts by brand, location, channel, and time of day in the tenant’s timezone.

  • Money that must always reconcile

    Wallets, auto-recharge, refunds, and partial cancellations all touch balances that must stay consistent.

Design and architecture decisions

  • Adapters behind one interface

    Payment providers and delivery partners each implement a single interface. Webhooks are verified with HMAC (and OAuth2 where partners require it) and retried through BullMQ.

  • Database per tenant, shared access layer

    Tenants keep separate PostgreSQL databases, while 30+ domain modules share one data-access layer for filtering, bulk upserts, export, and import.

  • Batch the lookups

    The pricing engine’s first version looked up overrides per item. Batching them into one PostgreSQL query per page removed the N+1.

  • Transactions and atomic counters

    Ordering uses PostgreSQL transactions for balances and ledgered refunds, and Redis Lua scripts for atomic queue numbers.

Selected implementation details

Loading the interactive reconstruction…

  • Payment gateway

    Stripe, Omise, PayNow QR, and an in-house gateway behind one adapter, with HMAC-verified webhooks and BullMQ retries.

  • Delivery integrations

    Deliveroo, Grab, and Delivery Hero: menu sync, order ingestion, store status, OAuth2/HMAC webhooks.

  • Delivery pipeline

    7 NestJS microservices on Kubernetes with Helm, helmfile, SOPS, and Traefik; 3 new services containerized with GitHub Actions to GHCR.

Outcomes

4payment providers behind one adapter
Stripe, Omise, PayNow QR, and an in-house gateway, chosen per tenant.
30+domain modules on one data-access layer
Database-per-tenant PostgreSQL with TypeORM.
1 queryper page for price overrides
Replaced an N+1 lookup in the pricing engine’s first version.
7NestJS microservices on Kubernetes delivery
Extended with Helm, helmfile, SOPS, and Traefik.

Figures come from my resume or from measuring the shipped product. Where a number describes the product or the team rather than my work, the context says so.

Technologies

  • NestJS
  • TypeScript
  • PostgreSQL
  • TypeORM
  • Redis
  • BullMQ
  • Docker
  • Kubernetes
  • Helm
  • GitHub Actions