UBBFY v2, the plan
Five workstreams that carry the platform into 2027, estimated in days and ordered by what depends on what.
Lead architect on a multi-tenant ERP, CRM and HR platform in production for many clients.
About ten companies run their operations on it, the largest of them managing two hundred employees and contractors. The platform is thirty-three server-side modules, 338 data models and close to four hundred screens, served in three languages: KPS, Planus, Flowplan, Gotolearn and People&Skill are the tenants in production.
I came onto a project already under way, written in Laravel on MySQL, and the first decision was to restructure it onto Django and PostgreSQL. Migrating data is thankless work that bills you late: timestamps carried over from the old database came in an hour behind, and that kind of gap never shows in review, it shows in production on somebody's timesheet.
The parts that decided the architecture were the ones nobody sees. Role-based access built to be configured rather than coded, so a new tenant does not mean a new deployment. An event bus on Celery, so a module can react to another without importing it. An audit trail, because a platform holding several companies' operations has to be able to answer what happened and who did it. Billing runs through Stripe and FedaPay together, which is what serving both European and West African clients actually requires.
What I did not see coming was internationalisation. I did not design for it, and retrofitting it onto a written codebase took the development environment down for days. The problem was not translation, it was the boundary: interface strings are mine, content typed by a tenant is theirs and has to exist in languages I do not choose. A notification now leaves in the language of whoever reads it rather than whoever triggered it. That is a decision I take on the first day of a project now, not in the sixth month.
The floor is held by tests: 3,146 on the server, 468 end-to-end runs through the browser.
Two separate applications in front of one API: an operations team and a business user do not need the same screens, and merging them would have produced one interface compromised for both. Modules talk through the bus instead of importing each other, so one can be added without touching the rest, and every write leaves a trace.


Five workstreams that carry the platform into 2027, estimated in days and ordered by what depends on what.