Zudomart
A Go modular monolith for African social commerce — 79 modules across five domains, escrow and three-tier verification, with a Python service for ranking, recommendation and fraud detection.
- 79
- Go modules
- 5
- Bounded domains
- 13k+
- Go source files
- 2
- Runtimes (Go + Python)
- Role
- Founder & lead engineer
- Year
- 2023 — present
- Type
- Social commerce super-app
01Overview
Zudomart is an Africa-first super-app: an integrated marketplace for goods, services and micro-gigs, with live commerce, short-form video and a multi-layer trust engine. Buyers discover products through creators, live shopping, reels and communities; creators monetise through subscriptions, gifts and affiliate commissions.
I founded it in 2023 and lead the engineering. In January 2026 it joined FasterCapital's EquityPilot programme, which put the current phase on milestones: harden escrow and fraud detection, pilot creator ad monetisation, and validate local payment integrations.
It is the largest system I have built. The backend is one deployable Go binary organised as 79 modules across five domains, beside a separate Python service owning everything model-shaped.
The engineering problem was never a single feature. It was keeping commerce, social and creator concerns from bleeding into each other while all three share users, payments and a feed.
02The problem
Social commerce is three products wearing one coat. A storefront has carts, inventory, escrow, refunds and tax. A social network has feeds, reels, comments and follows. A creator economy has livestreams, subscriptions, gifts and affiliate payouts. Each has a different consistency requirement and a different failure mode.
On top of that sits the reason the product exists at all. Africa's informal peer-to-peer economy runs on direct messages and cash, and it is heavily exposed to fraud — an estimated 65% of traders report losses to scams on informal platforms. A marketplace that does not solve trust is just another place to get robbed.
Building that as microservices from day one means paying distributed-systems tax — network hops, partial failures, deploy choreography, distributed transactions — before a single user justifies it. Building it as an unstructured monolith means the commerce code and the feed code fuse into something nobody can extract later.
So the constraint was: one process to operate, hard module boundaries inside it, and no module allowed to reach into another module's data.
03Architecture
- 01
Five domains, 79 modules
commerce (26 modules — products, categories, customers, carts, orders, payments, wallets, escrows, ledger, payouts, settlements, invoices, refunds, disputes, commissions, pricings, promotions, marketing, inventories, fulfillments, shipping, taxation, receipts, stores, wishlists, pos), social (14 — posts, feeds, stories, reels, videos, comments, reactions, likes, follows, reviews, brands, collections, jobs, audit), creator (5 — creators, livestreams, subscriptions, gifts, affiliates), platform (20 — admins, employees, api_keys, moderation, fraud, kyc, notifications, messages, mail, workflows, automation, events, jobs, support, settings, feature_flags, experimentation, integrations, achievements, audit) and core (14 — users, auths, profiles, verification, search, ai, ranking, recommendations, analytics, insights, reports, trends, subscriptions, i18n).
- 02
The trust engine
Three-tier verification gates what an account may do: browse, transact, or receive payouts. Escrow holds buyer funds until delivery is confirmed, with dispute windows and automated release timers. Fraud signals from the Python service feed back as account-level risk scores. Together these are the product — everything else is a marketplace anyone could build.
- 03
CQRS and an event spine
Modules never call each other's internals. Writes go through commands, reads through queries, and cross-domain effects travel as events over Kafka. An order paid in commerce becomes an event; the creator domain turns it into an affiliate commission; core turns it into a ranking signal. None of them import each other.
- 04
Layered dependency rule
shared/ holds cross-module type contracts — DTOs, models, permissions, responses. pkg/ holds domain-free Go libraries — auth, JWT, cache, money, resilience. platform/ holds infrastructure adapters — Redis, Kafka, S3, Postgres, gRPC, payments. Dependencies point inward only, which is what makes a module extractable.
- 05
Schema as the single source of truth
The database is defined once as ent schemas in db/, with Atlas generating versioned migrations from them. No hand-written DDL, and no drift between the ORM's idea of the schema and the database's.
- 06
Python service for the model layer
FastAPI with PyTorch and vector search, deployed separately: recommendation, ranking, moderation, vision, NLP and forecasting. Go owns transactions and correctness; Python owns anything that is a model artefact. Retraining a ranker must never require redeploying the payments path.
- 07
Deployment
Docker and Kubernetes manifests, Terraform for infrastructure, Traefik for ingress and a monitoring stack — all versioned in deployments/ next to the code they run.
04Key decisions
Modular monolith over microservices
One binary to deploy, one place to debug, one transaction boundary where it matters — but module boundaries strict enough that extracting any domain into its own service is a build-graph change, not a rewrite. The whole architecture rests on this.
Escrow on small transactions
Escrow is normal on large purchases and almost unheard of on the ₦2,000 trades that make up most of this market, because the fee model does not work. Making it work at that size — cheap holds, short windows, automated release — is the differentiator, and it is a state-machine problem before it is a payments problem.
ent + Atlas over a hand-rolled data layer
Code generation from schema gives compile-time safety across 79 modules touching one database. At this many entities, a runtime-typed ORM turns every migration into a manual audit.
Money as minor units, never floats
A dedicated money package in pkg/ carries currency alongside amount and refuses cross-currency arithmetic. Escrow, split payouts, affiliate commissions and refunds all compose from it, so rounding is decided in one place instead of thirty.
Go 1.26 and a small dependency surface
chi for routing, pgx for Postgres, ent for data, golang-jwt for tokens. Nearly everything else is standard library. Fewer dependencies means fewer upgrade cliffs on a codebase meant to last.
05Stack
- Go 1.26
- chi
- ent + Atlas
- PostgreSQL
- Redis
- Kafka
- Elasticsearch
- Python
- FastAPI
- PyTorch
- Docker
- Kubernetes
- Terraform