CAFM Monolith to Microservices
Decomposing an established facilities management monolith into independently sellable microservices - unlocking multi-tenancy, AI automation and a product model that lets each professional buy only what they need.
Overview
I joined this engagement as a product engineer, working hands-on with subject matter experts across FM, finance and compliance to decompose an established CAFM monolith into domain-driven microservices. The goal was commercial as much as technical - enabling a modular product model where each service could be sold independently to the professionals who actually needed it. Alongside the decomposition, I normalised the API layer, improved test performance, retrofitted multi-tenancy and introduced AI automation to eliminate manual document processing.
The Challenge
The existing platform was a mature Laravel monolith serving the UK facilities management sector. It worked - but the architecture was holding back commercial ambitions. The entire product was sold as a single package, meaning FM professionals paid for finance features they didn't need, and finance professionals paid for FM features they'd never touch. The deployment model was equally rigid: each client got their own database and API instance, spun up through a CI/CD pipeline. Safe, but expensive to operate and impossible to scale efficiently.
- Decompose the monolith into independently deployable services aligned to business domains
- Enable a modular product model where each service can be sold separately or as a bundle
- Retrofit true multi-tenancy to replace the one-database-per-client deployment model
- Normalise inconsistent API patterns and data structures across the codebase
- Introduce AI automation to eliminate manual processing of quotes, invoices and documents
- Continue supporting and shipping features to the production platform throughout
The Approach
The decomposition followed a domain-driven design approach, identifying core business areas and drawing service boundaries around them. Rather than a big-bang rewrite, each domain was extracted incrementally using a strangler fig pattern - the monolith continued serving production traffic while services were carved out behind it. I worked in weekly rotations with subject matter experts from each business domain - FM operations, finance, compliance - to ensure what we were building matched their vision and workflows. This hands-on, agentic approach meant we weren't guessing at domain boundaries from the outside; we were modelling them alongside the people who lived in them daily.
Multi-Tenancy
The original platform deployed a separate database and API instance per client through CI/CD automation. It was safe but operationally heavy and didn't scale. The rebuild introduced proper multi-tenancy using an API-first approach with JWT authentication and tenant-scoped claims. Each service validates tenant context from the token, resolves the correct data scope, and enforces isolation at the query level. This eliminated the per-client infrastructure overhead while maintaining strict data separation between organisations.
AI Automation
A key part of the engagement was identifying and automating manual pain points that consumed significant operational time. Using both OpenAI and Claude APIs, I built agentic workflows that could read, interpret and process quotes and invoices - documents that previously required manual review, data extraction and system entry. The AI agents handle structured and unstructured document formats, extract relevant line items and financial data, and feed them directly into the appropriate service for approval or further processing.
API Normalisation & Test Performance
The monolith had grown organically over several years, resulting in inconsistent API patterns, varied response structures and duplicated data access logic. Part of the modernisation involved normalising the API layer - establishing consistent REST conventions, standardising error handling, and introducing GraphQL where the front end needed flexible querying. The test suite had also degraded in performance, slowing down CI feedback loops. I profiled and restructured the tests, reducing execution time significantly and making them a reliable gate rather than a bottleneck.
Engineering Standards
The codebase enforces PHPStan at level 9 with 100% type coverage across all backend services. Every service runs its own test suite, and CI pipelines gate every push with static analysis, tests and code style checks. The shared authentication and tenancy logic is covered by integration tests validating isolation boundaries across service and tenant contexts.
Technology Stack
Technical Challenges
Strangler Fig Decomposition Under Live Traffic
Incrementally extracted domain boundaries from the monolith into independent services while the production platform continued serving clients. Each extraction was sequenced to minimise risk - new services sat behind the monolith initially, with traffic gradually shifted once validated.
Retrofitting Multi-Tenancy Into a Single-Tenant Architecture
Replaced a per-client database and API deployment model with JWT-based multi-tenancy. Tenant identity is carried in token claims, validated at the middleware layer, and used to scope every query - eliminating per-client infrastructure while maintaining strict data isolation.
AI Document Processing for Unstructured Inputs
Built agentic AI workflows using OpenAI and Claude APIs to read and process quotes and invoices in varied formats. The agents extract structured data from unstructured documents, handle edge cases in formatting and terminology, and feed results directly into the relevant service for approval.
Normalising an Organically Grown API Surface
Audited and standardised inconsistent API patterns, response structures and data access logic that had accumulated over years of feature development. Established consistent REST conventions and introduced GraphQL for complex front-end queries, providing a clean contract for the new service-oriented architecture.