# Enterprise B2B Platform

Took a legacy codebase everyone was afraid to touch and turned it into a system the team actually enjoys working on.

Source: https://miloscvetkovic.dev/work/enterprise-b2b-platform

- Tagline: legacy rescue
- Category: PLATFORM
- Status: PRODUCTION
- Metric: 40% less complexity
- Basis: Complexity of the codebase after its module-by-module move to Clean Architecture, against the legacy codebase before it.
- Tags: React, Node.js, PostgreSQL, Terraform
- Published: 2026-09-09
- Updated: 2026-10-01

## The Challenge

The codebase had a reputation, and it had earned it. Validation was manual and happened... sometimes. Tests? What tests? Without them, every change was a guess about what else might break, and nobody wanted to be the one guessing. Deploys were no longer fast, either. None of that bought any patience from the business, which needed new features yesterday. So the real problem was never just messy code: it was how to keep shipping those features on a foundation that made every one of them risky, without stopping everything to fix it first.

## My Approach

I introduced boundaries gradually. Clean Architecture emerged one module at a time, with controllers, services and repositories each taking one job, so data access got a layer of its own. Manual validation gave way to Zod schemas, whose inferred types keep the checks and the code from drifting apart. I built a background job system on pg-boss for async operations; it keeps its queue in PostgreSQL, so there is no broker to run. The delivery path got the same treatment. CI/CD is built from reusable GitHub composite actions, and Nx's affected commands limit builds, tests and deploys to the projects a change affects. Gitleaks, npm audit and Trivy scan on pushes, pull requests and a weekly schedule. Terraform keeps one remote state file per root directory, with production in a root of its own, and gives each developer a throwaway copy of the stack under a state file of its own; it runs a plan on every pull request that touches the infrastructure and waits for an approval before it applies to production. Playwright E2E tests, written with the Page Object pattern, are sharded four ways. Every PR shipped value while improving the foundation underneath.

## Key Contributions

- Migrated the codebase to Clean Architecture (controllers → services → repositories)
- Replaced manual validation with Zod schemas and type inference
- Built background job system with pg-boss for async operations
- Architected modular CI/CD with reusable GitHub composite actions
- Implemented security scanning (Gitleaks, npm audit, Trivy)
- Designed multi-environment Terraform architecture with state isolation
- Established Playwright E2E testing with Page Object pattern and 4-way sharding

## Impact

- New developers ship features in their first week
- CI runs only what changed—deploys are fast again
- Bug rate dropped as test coverage climbed
- Security scans (Gitleaks, npm audit, Trivy) run on pushes, pull requests and a weekly schedule
- Infrastructure changes are reviewed like code, not YOLO'd

## Lessons

- Replace manual validation with Zod schemas and infer the types from them, so the checks and the code stay in step.
- Tests are part of the rescue rather than a reward for finishing it.
- Infrastructure changes deserve the same review as code, and a multi-environment Terraform architecture with state isolation puts infrastructure in code, where it can get that review.

## Tech Stack

| Category | Items |
| --- | --- |
| Frontend | React 18, Material-UI, Vite, TypeScript |
| Backend | Express.js, Node.js, TypeORM, Zod |
| Database | PostgreSQL, pg-boss |
| Testing | Jest, Playwright, Supertest |
| Infrastructure | Azure App Service, Azure Container Apps, Terraform |
| CI/CD | GitHub Actions, Nx |
