CarmateKH
Building Cambodia's Automotive Marketplace from Zero
Cambodia's automotive marketplace — a dual-sided platform connecting car buyers with individual sellers, dealerships, OEM brands, and financial institutions. Three distinct user groups served through dedicated frontends: a consumer portal for browsing and lead generation, a SaaS-style seller portal for OEM brands and dealerships, and a superadmin panel for internal operations.
I joined in mid-2021 as the first full-time engineer, inherited a fragmented legacy codebase with no documentation and zero server-side rendering, and rebuilt the entire platform across 5 generations while keeping it live throughout.
Four Pivots. One Platform.
The most honest thing I can say about CarmateKH is that it survived four complete business model changes. Most codebases don't. The architecture decisions I made early — polymorphic data models, composable RBAC, domain-grouped monolith — are the reason the platform didn't require a full rewrite each time the business changed direction.
Used Car Dealers
2019–2021The founding Korean team built the MVP around onboarding used car dealers. Cambodia's dealer market wasn't ready — most operated informally with no digital presence. Adoption stalled. The founding team handed over technical ownership. I inherited the codebase.
Individual Sellers & Manual Inventory Seeding
2022With dealers unwilling to self-manage listings, we contacted individual car sellers on Khmer24 — Cambodia's dominant classifieds platform — and manually reposted their vehicles on CarmateKH with permission. A classic marketplace cold-start strategy: seed supply manually to attract organic demand. The operational cost was too high to sustain, but the insight was invaluable — individual sellers wanted to list their own cars if the process was simple enough. That became the "Sell Your Car" UGC funnel built later.
Bank Auction Infrastructure
2022The company signed a deal with KDSB Bank to sell repossessed vehicles through live auctions. I built the entire auction infrastructure from scratch: full lifecycle engine (SCHEDULED → ACTIVE → CLOSED → ARCHIVED), OTP-gated public registration, a bank admin portal, and an 847-line auction controller handling CRUD, state transitions, and paginated status-grouped queries. The system worked. The business model didn't — banks refused to pay commission. KDSB cancelled the contract. But the polymorphic auction engine, OTP flows, multi-seller RBAC, and public event pages became reusable platform primitives that accelerated every subsequent feature.
New Car Research & OEM Lead Generation
2023–PresentAfter the bank pivot, we identified the real gap: Cambodian consumers searching for new car pricing and specifications had nowhere credible to go. Rebuilt the consumer frontend as a Next.js SSR application — unlocking organic search traffic as the primary acquisition channel. Built SEO infrastructure from scratch with structured data, dynamic sitemaps, slug-based routing, and per-locale metadata in 4 languages. Ranked on first pages of Google. Signed OEM brand partnerships — Toyota, Hyundai, Lexus, MG, BYD and others manage digital showrooms through the Seller Portal with B2B subscriptions.
Engineering Workflow
All code goes through a PR-based review workflow on GitHub — no direct pushes to main. As the platform evolved, 3 additional developers joined at different stages for frontend and backend support. I onboarded each one, reviewed their PRs, and kept the architecture consistent across the codebase. Major architecture decisions are documented in markdown before implementation, and Jira keeps sprint planning and task tracking visible across the team.
Observability closes the loop: Sentry error tracking, New Relic APM, custom error pipelines, and uptime monitoring all feed back into architecture decisions. The role isn't just building features; it's aligning with the co-founders on priorities, reviewing code, documenting trade-offs, and iterating from production feedback.
Technical Architecture
Key Engineering Decisions
Every major architectural decision was a deliberate tradeoff, not a default:
Monolithic backend, multi-frontend architecture
A microservices approach was overkill for a 1–2 person team. A single Express API served four independent frontends including a React Native mobile app, letting me iterate 3–5x faster on business logic. Each frontend remained independently deployable via Docker standalone builds.
Polymorphic data modeling
Optional references (_dealership || _company || _officialBrand) let banks, dealers, and OEM brands share the same auction engine, API routes, and UI without coupling. When KDSB left, zero code was thrown away.
Dual caching strategy
Redis for shared state (car detail pages, analytics results) with in-memory LRU for hot paths. Sliding-window rate limiter (443 lines) with intelligent bypass for SSR traffic and internal IPs.
Observer pub-sub for cross-cutting concerns
Analytics, SMS (Mekong + Twilio), Firebase push notifications, and auction status changes are all decoupled from core business logic through a custom event system.
Zod-validated environment configuration
The server refuses to boot with missing or malformed env vars. Eliminated an entire class of production configuration bugs.
Three fully isolated environments
Local, dev, and production — each with scoped AWS S3 buckets, per-environment IAM policies, and separate Google API keys. GitHub Actions CI/CD handles environment-aware deployments.
Platform Evolution — 5 Generations
| Gen | Period | Description |
|---|---|---|
| v1 | 2019–2021 | Inherited Korean MVP — React SPA, no SSR, fragmented backend |
| v2 | 2021–2022 | Full rewrite — Express 4 API, MongoDB, React frontends, Docker infrastructure |
| v3 | 2022 | Auction engine + bank portal, OTP flows, polymorphic seller models |
| v4 | 2023 | Next.js SSR consumer frontend, SEO infrastructure, 4-language localization |
| v5 | 2024–Present | Express 5, Node 22, native ad server, B2B seller portal, observability stack (New Relic + Sentry) |
What I Learned the Hard Way
Monoliths are underrated for early-stage products.
A single Express API serving four frontends let me move faster than any microservices alternative would have. The key was maintaining clean domain boundaries within the monolith so decomposition remains possible when scale demands it.
Failed partnerships still produce infrastructure.
The KDSB Bank contract collapsed. The auction system, OTP registration flow, multi-seller RBAC, and public event pages it produced did not. Every one of those components is active infrastructure today. When you build things properly, they outlive the deals that funded them.
Documentation is infrastructure, not overhead.
The carmate-docs repository — 90+ pages covering architecture, data models, API routes, conventions, and cross-repo dependencies — became the single source of truth for onboarding contractors, maintaining consistency across 9 repos, and making architectural decisions reviewable.
SSR is a business decision, not just a technical one.
Moving from client-rendered React to Next.js SSR directly changed the growth equation. In a market where organic search is the primary acquisition channel and paid marketing budget is limited, server-side rendering wasn't a technical nicety — it was the product strategy.
Current Status
The platform is live at carmatekh.com. The technical foundation is complete: 4 production applications, full observability stack, CI/CD pipelines, multi-environment infrastructure, SEO-ranked pages in 4 languages, and a seller portal ready for B2B onboarding.
CarmateKH pivoted four times. The modular backend survived all four because the data models were designed to be extensible rather than single-purpose. The Company collection built for KDSB Bank now serves any B2B partner; the auction engine built for repossessed cars works for any seller type; the UGC sell-your-car funnel grew directly out of lessons from manually seeding individual seller listings in 2022.