Skip to content
All work
01Social commerce super-app2023 — present

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

  1. 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).

  2. 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.

  3. 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.

  4. 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.

  5. 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.

  6. 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.

  7. 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

Decision 01

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.

Decision 02

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.

Decision 03

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.

Decision 04

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.

Decision 05

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