Skip to content
All work
15E-commerce platform2026

Telente Store

A modular-monolith commerce platform: 24 hexagonal modules, 150+ routes, 31 relational models — storefront, admin dashboard and API in one process.

24
Feature modules
150+
API routes
31
Relational models
1
Deployable process
Role
Author
Year
2026
Type
E-commerce platform

01Overview

Telente Store is a production e-commerce platform built as a modular monolith: 24 feature modules, each with a hexagonal ports-and-adapters layout, unified by a lightweight DI container and CQRS-style command and query buses.

A single Node.js process serves a REST API with 150+ routes, a vanilla storefront with clean URLs, and a full admin dashboard for catalogue, orders, inventory, users, returns and support.

It is the project where the modular-monolith pattern I later scaled up in Zudomart was worked out.

02The problem

Commerce has an unforgiving domain model. Inventory with variants, carts, orders, payments, shipping, returns, refunds, coupons, tax rules and reviews all touch each other, and getting any transition wrong costs real money.

Most small commerce codebases collapse into a controllers folder and a services folder, at which point the order lifecycle is spread across a dozen files and nobody can say where a refund is authorised.

The goal was a codebase where each part of the domain has one obvious home and the boundaries between them are enforced by structure rather than convention.

03Architecture

  1. 01

    24 hexagonal modules

    Each module owns its domain, ports and adapters. Nothing reaches across a boundary except through a declared port, so swapping a payment provider or an email transport touches one adapter.

  2. 02

    DI container and CQRS buses

    A lightweight container wires modules together; command and query buses separate writes from reads. Routes dispatch to the bus rather than calling services directly, which keeps HTTP concerns out of the domain.

  3. 03

    31 relational models

    Prisma over MySQL 8.4 covering catalogue, variant inventory, carts, orders, payments, shipping, returns, refunds, coupons, reviews, notifications and email delivery tracking.

  4. 04

    Storefront and admin from one process

    An editorial vanilla storefront (home, listing, product detail with gallery, cart, checkout with coupons/tax/shipping, account, wishlist, returns, public order tracking) and a full admin dashboard, both served with clean-URL routing by the same Fastify instance.

  5. 05

    Inventory as a ledger

    Stock is not a number that gets updated. Every movement is an entry, with low-stock thresholds computed over the ledger — so a discrepancy can be traced instead of discovered.

  6. 06

    Platform concerns

    Paystack payments with webhook handling, email delivery through Resend/SendByte with delivery-status tracking, OTP auth, rate limiting, Helmet, CORS hardening, branded HTML error pages, and a Dockerised MySQL + backend with health checks.

04Key decisions

Decision 01

One process, 24 modules

A store this size does not need a service mesh. It needs internal boundaries good enough that the twenty-fifth module does not make the previous twenty-four harder to change.

Decision 02

TypeScript 5.9 strict, ESM, NodeNext

Strictest reasonable settings from the first commit. Retrofitting strictness onto 24 modules and 31 models is a project of its own.

Decision 03

Stock movements over stock counts

Storing the ledger and deriving the level means overselling is a reconstructable event rather than a mystery.

Decision 04

Vanilla storefront with a real design system

No framework on the client, but a genuine editorial design system in CSS. Fast pages, no hydration, and full control over checkout — the one flow where a surprise is unacceptable.

05Stack

  • TypeScript 5.9
  • Fastify 5
  • Prisma
  • MySQL 8.4
  • Node.js 24
  • Paystack
  • Resend
  • Docker
  • Swagger