Product and software development
I build multi-tenant web and mobile products with Angular, Ionic/Capacitor and Node.js. I take two kinds of work: greenfield builds, and takeovers — making an undocumented codebase whose original developer has left maintainable again.
What stack do I work in?
Angular on the front end with Ionic/Capacitor for mobile, Node.js and Express with Sequelize on the back end, MySQL and SQLite for data, Redis with BullMQ for queues, MinIO for object storage. Delivery runs on Docker Compose and GitHub Actions. I chose this stack for one reason: one team can run web and mobile from a single codebase.
- Front end
- Angular · TypeScript
- Mobile
- Ionic · Capacitor · (previously Flutter)
- Back end
- Node.js · Express · Sequelize
- Data
- MySQL 8 · SQLite · Redis
- Infrastructure
- Docker Compose · nginx · GitHub Actions
- Desktop
- Tauri 2 · Rust · embedded SQLite
Why is multi-tenant architecture a separate skill?
In a multi-tenant system one codebase and one database serve many customers. The difficulty is not scale, it is isolation: every query, every file access and every background job must be scoped to a tenant. Forget it in one place and the result is not a performance issue — it is a data leak.
- Query-level isolation. The tenant identifier is not an optional filter; it is a mandatory part of the data layer.
- Background jobs. Every queued job carries its own tenant identifier in the payload. There is no “currently active tenant” in a worker, and assuming there is, is the most common failure.
- Object storage. Paths are partitioned by tenant; signed URLs are bounded in scope and lifetime.
- Migration discipline. Schema changes are additive, not destructive — expand and contract: add the new column, have the code write both, then drop the old one. Risking every tenant in a single migration step is not acceptable.
- The role of tests. Isolation rules are protected by tests, not by convention. Tenant-leak tests are the most critical part of the suite.
I applied this discipline in production, not in theory: a multi-tenant CRM split into 19 module groups and protected by over 4,000 automated tests. The technical detail is here.
How do I start on a codebase I did not write?
The first job on an inherited codebase is mapping, not coding. The first one to two weeks go into an audit: what actually works, what only appears to work, and where the three riskiest points are — reported at file and line level. Only after that map do I start changing anything.
- Can it run: does the project come up locally, and how long does that take.
- Boundaries: data model, authorisation rules and external dependencies are extracted.
- Risk sweep: authentication, money arithmetic, data isolation and migration steps are reviewed separately.
- Test state: which areas are covered and which are not. The intersection of untested and risky is closed first.
- Sequencing: findings are ordered by impact, and the top three become the next slice of work.
The audit can be bought on its own, with no code changes — just a findings report. Before committing to a takeover, knowing what you are buying is usually the cheapest step available.
What does AI-assisted development actually change?
AI-assisted development increases how much code one person can produce. It does not raise the quality ceiling. In my own measurements the model matters far less than the harness and the task design, which means architecture decisions and review get more important, not less.
Changing the harness moved scores by about ±11 points, changing how the task and prompt were written by about ±18, and changing sampling parameters by only ±2–3. In other words, “which model” is a small question next to “how did you describe the work”. Measurement detail.
- Every change is covered by tests; generated code is not merged without review.
- “Done” has a fixed definition: tests and lint green, or the work is not done.
- Each project keeps a written rules file — version numbers, domain invariants and constraints live there.
- No invented APIs; any uncertain call is verified against release notes.
Product development: frequently asked questions
How long does it take to build a product from scratch?
A usable first version takes between 6 weeks and 4 months. A multi-tenant product with role-based authorisation and a mobile counterpart takes 6–9 months. Duration is driven by the number of rules rather than the number of screens: pricing, tax, discount and permission rules are what stretch a timeline.
Is the mobile app a separate project?
With Ionic and Capacitor it is a second build target of the same codebase, not a separate project. Changes made on the web are mirrored to mobile, and that mirroring is enforced as a written rule rather than left to intention. If a requirement genuinely needs native behaviour, it is scoped separately.
Who owns the code?
You do. The repository lives in your organisation and I contribute to it. Handover includes deployment scripts, an operations document and an environment variable inventory. A delivery your own team cannot take over is not a delivery.
Will you take a project with no tests?
Yes, but writing tests is not the first move. First the three riskiest areas are identified — usually authentication, money arithmetic and data isolation — and tests start there. Trying to cover an entire inherited codebase is the worst possible use of the first month.
Last updated: