Skip to content
Case study · Interface.ai

Consolidating seven apps into one platform

How 100+ banks went from juggling seven logins to a single microfrontend platform that loads three times faster.

7 → 1

applications consolidated

Role

Architecture proposal, frontend lead

Timeframe

2024 – 2026

Stack

React · Module Federation · Monorepo · Clerk · TypeScript

The problem

Interface.ai's conversational AI platform had grown one product at a time, and it showed. By 2024, more than a hundred banks and credit unions were operating across seven separate applications — seven login flows, seven navigation patterns, seven slightly different design languages. Each app bundled its own React instance and its own copy of every vendor library.

The user-facing symptom was brutal: 5–6 second page loads and constant context-switching for bank operations teams. The engineering symptom was worse: every cross-cutting change (auth, theming, telemetry) had to be implemented seven times, and drift between the apps compounded with every release.

The constraints

  • All seven apps had to keep working for live banking customers throughout the migration — no downtime, no big-bang cutover.
  • Teams owned their apps independently; the architecture had to preserve autonomous deploys rather than force a single release train.
  • Banking customers meant strict auth and RBAC requirements — permissions could not regress for a single tenant.
  • The business would not pause feature work for a rewrite. The consolidation had to happen alongside normal delivery.
The architecture, before and after

Admin Console

own React
own auth
own deploy

Analytics

own React
own auth
own deploy

Bot Builder

own React
own auth
own deploy

Knowledge Base

own React
own auth
own deploy

Agent Desktop

own React
own auth
own deploy

Reporting

own React
own auth
own deploy

Settings

own React
own auth
own deploy

7 logins
5–6s loads
every change ×7

Decisions & trade-offs

Monorepo + microfrontends over a single merged app

I proposed a monorepo with Module Federation microfrontends: one shell owning auth, navigation, and design tokens, with each legacy app migrating in as a federated remote. Teams kept independent deployability; users got one coherent product.

Trade-off: Module Federation added real build complexity and version-coupling discipline — upgrading React affects every remote. A single merged SPA would have been simpler but would have serialized seven teams into one deploy queue.

Centralized auth with Clerk + RBAC in the shell

Authentication and role-based access moved into the shell as a platform capability. Remotes consume the session rather than implementing login. One security review surface instead of seven.

Trade-off: Every app had to migrate off its own auth flow, which meant carefully mapping seven permission models onto one RBAC scheme before any UI work could land.

Incremental tenant migration, dual-running systems

Tenants moved to the unified platform in waves while old apps stayed live. A shared vendor chunk, per-route code splitting, and parallelized API calls landed as part of the same effort.

Trade-off: Dual-running meant maintaining two deployment pipelines for months. The upfront cost was real — the hardest part of the project wasn't the design, it was convincing stakeholders the payoff justified it.

The outcome

Seven legacy applications became one Unification platform. Page load dropped from 5–6 seconds to 1–2 seconds, and the Lighthouse performance score climbed from roughly 45 to 85+.

Cross-cutting changes now land once instead of seven times. New micro-apps join the platform through an established pattern rather than a fresh negotiation — the architecture scaled cleanly as products were added.

Apps to maintain

Before
7
After
1

Page load

Before
5–6s
After
1–2s

Lighthouse score

Before
~45
After
85+

What I'd do differently

I'd invest in contract tests between the shell and remotes from day one. We caught integration drift in staging more often than I'd like; explicit contracts would have caught it in CI.

I'd also push for a shared design-token package before the first remote migrated instead of midway through — retrofitting tokens across three already-migrated apps was avoidable churn.