OutSystems Tech Lead study materials
OutSystems Tech Lead study resources

Extracting Services from a Monolithic Policy Module

OutSystems Tech Lead · Put your knowledge to work in context.

All case studies

Extracting Services from a Monolithic Policy Module

A mid-sized insurer runs its policy administration on OutSystems 11. The core 'PolicyCore' module has grown to 180 screens, 420 server actions and 65 entities, and is referenced by five applications: broker portal, customer portal, claims, billing and a mobile app. Four squads commit to the same module. 1-Click Publish in Development now takes 11 minutes, and a deployment plan to Production takes 45 minutes. Merge conflicts occur weekly, and the Architecture Dashboard shows 14 cyclic dependencies between PolicyCore and a shared 'CommonUtils' module. The business wants a partner API and a new mobile app within a six-month roadmap, and the current release train slips by 3-5 days each month. Constraints: no big-bang rewrite; production release window is monthly; two squads are new to OutSystems. The tech lead must propose a target module architecture and a safe sequence.

1. Propose a target decomposition and the first extraction you would fund. Justify it by coupling, risk and the six-month constraint.

Read the worked answer

Target: bounded contexts Policy, Customer, Billing, Documents, and a thin PolicyCore facade. Put owned data and public actions in service modules; put stateless helpers in library modules. Do not start with Policy: it is the highest-coupling, highest-risk area. First fund a two-sprint dependency cleanup: move CommonUtils helpers into a library, break the 14 cycles, and add dependency rules. Then extract Customer as a service module because it is read-heavy, has a clear contract, and is reused by all five apps. Wrap existing PolicyCore calls in a facade so consumers do not need a big-bang change; migrate one consumer, the broker portal, first. Sequence: cleanup, Customer service, facade, broker, mobile/partner, Billing, Policy. This respects the monthly release window and the two inexperienced squads because each step is independently deployable and reversible. Do not split entities across modules without an owner; use service actions, not direct cross-module entity reads. Track cross-module references and publish time per module as leading indicators.

2. How would you keep the partner API and mobile app from re-coupling to PolicyCore?

Read the worked answer

Introduce a dedicated 'PartnerAPI' module and a 'MobileGateway' module that expose coarse-grained, versioned contracts. They call service modules, not PolicyCore internals. Publish only public actions; keep entities private; use request and response structures rather than entity records. Contract-first: define structures and error codes; version in the URL or header; never expose internal entity IDs unless they are stable. Apply authentication and authorization at the gateway; map partner scopes to roles and permissions. For the mobile app, use a mobile service module with task-specific actions such as GetMyPolicies and GetPolicyDetail rather than generic CRUD. This reduces chatty calls and shields the app from domain changes. Enforce with architecture review: a new dependency from PartnerAPI to PolicyCore is a design defect. Add integration tests against the contract. If a use case needs PolicyCore data, add a public action to the Policy service and let the facade compose it. This keeps partner and mobile channels independently deployable and prevents a second monolith.

3. Which leading and lagging indicators would show the decomposition is working?

Read the worked answer

Leading: number of cyclic dependencies (target 0), cross-module references per app, average 1-Click Publish time per module (target under 3 minutes), merge-conflict count per sprint, review time, and percentage of changes confined to one module. Lagging: deployment frequency, lead time from commit to production, change failure rate, MTTR, and incidents caused by shared-module changes. Also track consumer migration: how many apps use the facade versus direct PolicyCore. Set a baseline in week 1 and review monthly. Do not use lines of code or module count as success; a small module with high fan-in can still be a bottleneck. If publish time falls but change failure rate rises, the split is wrong. Use the Architecture Dashboard to verify dependency direction, and sample two deployments per month to confirm no hidden cross-module entity reads.