← Back to Projects

Case Study

Insamed

Insamed is a multi-tenant healthcare operations platform for Indonesian pharmacies and clinics, connecting pharmacy POS, FEFO inventory, patient reception, clinical documentation, billing, reporting, and BPJS workflows through a branch-scoped web application and API.

Outcome

Connects pharmacy sales and clinic visits to inventory, clinical records, billing, payments, audit trails, and BPJS submission workflows.

  • TypeScript
  • Next.js
  • NestJS
  • Fastify
  • PostgreSQL
  • Drizzle ORM
  • Redis
  • BullMQ
Insamed project preview

Problem & Context

What Needed to Change.

Indonesian pharmacies and clinics need to coordinate sales, expiring medicine stock, prescriptions, patient visits, clinical records, billing, payments, and BPJS administration without losing tenant, branch, or staff attribution across handoffs.

The platform supports multi-branch pharmacy and clinic operators, with workflows for cashiers, pharmacists, inventory staff, receptionists, doctors, nurses, finance staff, tenant administrators, and platform administrators.

Constraints & Tradeoffs

The Shape of the Decision Space.

Constraints

  • Every tenant-owned operation must preserve tenant scope, and branch-operational writes require an explicit branch context.
  • Rupiah amounts are stored and calculated as integers, while inventory quantities must never become negative.
  • Clinical and identity data require permission separation, PII-safe logs, redacted audit payloads, and attributable changes.
  • BPJS communication is an external, failure-prone dependency, so clinical completion cannot depend on immediate gateway availability.

Tradeoffs

  • A modular monolith keeps deployment and cross-domain transactions simple, but modules cannot be scaled or released independently like services.
  • Tenant and branch predicates are written explicitly in queries for clarity and control, at the cost of repetitive code and no automatic type-level enforcement.
  • Redis-backed jobs are optional and disabled by default, reducing local infrastructure requirements while leaving scheduled BPJS sending unavailable until enabled.
  • Runtime feature access is driven by tenant module records instead of tenant type, enabling flexible product bundles but adding provisioning and route-gating complexity.

Architecture

A Deliberately Legible System.

  1. 01

    Web Application

    Next.js App Router pages render Indonesian-language workflows and compose authentication, branch selection, internationalization, notifications, and TanStack Query state.

  2. 02

    Scoped API Client

    The browser client attaches the access token and selected branch, refreshes expired sessions, and clears cached data when the active branch changes.

  3. 03

    Fastify Transport

    NestJS runs on Fastify with versioned API routes, request IDs, CORS, multipart limits, API documentation, and structured exception handling.

  4. 04

    Authorization and Validation

    Controllers combine authentication, tenant, branch, module, and permission guards with Zod validation before invoking domain services.

  5. 05

    Domain Transactions

    Services coordinate sales, FEFO stock consumption, clinic state transitions, clinical finalization, billing, payments, and audit records inside scoped transactions.

  6. 06

    PostgreSQL Persistence

    Drizzle maps tenant- and branch-aware tables for integer money values, inventory batches, immutable stock movements, clinical records, invoices, payments, and BPJS submission state.

  7. 07

    Background Integration

    When enabled, BullMQ and Redis provide retryable jobs and scheduled BPJS processing while restoring tenant and branch context for each operation.

Screens & States

The Interface in Context.

Temporary placeholder artwork for an Insamed pharmacy point-of-sale screen
Temporary placeholder — replace with an anonymized pharmacy POS capture using seeded data.
Temporary placeholder artwork for an Insamed clinic and BPJS workflow screen
Temporary placeholder — replace with an anonymized clinic or BPJS workflow capture using seeded data.

Results

What the System Delivers.

  • Pharmacy sales with draft autosave, payments, prescription checkout, returns, and branch-scoped sale numbers.
  • FEFO batch consumption, unit conversion, guarded stock updates, stock opname, transfers, and append-only stock movement records.
  • A clinic workflow connecting reception, queues, clinical documentation, finalization, invoicing, and payment attribution.
  • BPJS validation, dependency ordering, retry handling, duplicate protection, correction notes, and optional scheduled delivery.

Lessons

What I Would Carry Forward.

  • Multi-tenancy requires explicit tenant and branch predicates on every read and write, including mutation conditions.
  • Inventory correctness needs a single transaction covering FEFO selection, guarded quantity updates, payment state, and a durable movement ledger.
  • External healthcare integrations are safer when deterministic payload construction is separated from retryable network delivery and duplicate protection.
  • Shared validation schemas and focused property tests strengthen state machines, role boundaries, date handling, and cross-package request contracts.