How We Built a Unified Platform Without Breaking the Bank (Lessons, Stack, and Tradeoffs)
A "unified platform" sounds expensive, slow, and risky-like a multi-quarter rewrite that eats your roadmap.
Ours wasn't. We stitched together a single experience across products, data, and workflows while keeping costs sane and shipping value every few weeks.
This post walks through what we did, what we deliberately didn't do, and the practical tactics that kept us from building a gold-plated platform nobody asked for.
Start With the Unification You Actually Need (Not the One That Looks Great on a Diagram)
Before we wrote a line of platform code, we made a simple list: what is "broken" for customers today?
In our case, it wasn't "we need microservices" or "we need a platform." It was:
1) Multiple logins across tools (support tickets were constant)
2) Inconsistent permissions (people got access to the wrong thing)
3) Data didn't match between products (reports were distrusted)
4) Integrations were duplicated (every team re-built the same connector)
So we defined unification in customer terms:
- One identity and session
- One permissions model
- One "source of truth" for core entities (customers, workspaces, billing)
- One consistent way to integrate and automate
Then we wrote a "platform charter" with two guardrails:
- If it doesn't reduce customer friction or engineering duplication in the next 90 days, it's not platform work.
- If a platform decision increases ongoing complexity, it must pay for itself with measurable savings.
Practical example: we had three separate "Account" tables across systems. Instead of forcing a massive data migration, we chose one canonical "Workspace" concept with a minimal schema (id, name, owner_id, plan_id). Everything else remained in product databases and was referenced by workspace_id.
That single move enabled unified login, consistent entitlements, and cross-product navigation-without boiling the ocean.
Design the Architecture Around Thin Standards, Not Thick Rewrites
The cheapest unified platform is the one that standardizes "edges" while leaving existing product internals mostly intact.
We focused on four thin layers:
**1) Identity + session (SSO)
We implemented a single auth provider (OIDC) and a shared session cookie across apps under one domain. We did not rewrite each product's authorization logic on day one.
Instead, each app accepted a signed token with:
- user_id
- workspace_id
- roles/scopes
- feature flags
This gave us an immediate "one login" experience, plus a consistent way to pass identity between services.
Cost-saving tactic: we didn't build custom auth infrastructure. We used a managed identity provider and kept our custom code limited to:
- token claims mapping
- tenant/workspace selection
- an admin UI for roles
**2) A permissions model that's simple enough to ship
We avoided the trap of designing perfect RBAC/ABAC upfront. Our first version was:
- Roles: Owner, Admin, Member, Read-only
- Scopes: billing:read, billing:write, data:read, data:write
We stored roles at the workspace level and scopes at the product feature level.
Practical example: if Product A had "Export Data," we guarded it behind a scope like productA:export. Later, when customers asked for "allow exports but not deletes," we added a narrower scope rather than rewriting the whole model.
**3) Canonical entities via a small "platform core" service
We created a single lightweight service for:
- Workspaces
- Users (as a directory, not the full profile)
- Plans and entitlements
Everything else stayed decentralized.
The goal was not "all data in one place." The goal was "consistent keys and entitlements everywhere."
We used a simple API contract:
- GET /workspaces/{id}
- GET /workspaces/{id}/entitlements
- GET /users/{id}
And we cached aggressively at the edge because these are read-heavy.
**4) One integration pattern, not one integration platform (at first)
Teams were building the same connectors over and over: Slack notifications, webhook deliveries, CRM sync.
We standardized on:
- Outbound webhooks with retries + signing
- An events topic (e.g., "workspace.created", "invoice.paid")
- A shared "connector toolkit" library with auth helpers, pagination patterns, and logging
We did not build a full-blown iPaaS. We created a repeatable pattern that made the next integration 30-50% cheaper.
Keep Costs Low With Sequenced Migrations and "Strangler" Releases
The biggest platform cost isn't cloud spend-it's the organizational tax of a long-running rewrite.
We kept momentum (and budget) by sequencing migrations in small, reversible steps.
Step 1: Unify the front door (navigation + sessions)
We shipped a "shell" app: a thin UI that handled login, workspace switching, global navigation, and a shared settings area. Each product remained its own app, embedded via links or lightweight routing.
Why it worked: customers felt like they were in one system, even though the internals were still separate.
Step 2: Move settings and billing into the shell
Settings was the most duplicated area across products. We moved:
- team management
- roles
- billing and invoices
into one place first. That reduced support burden immediately.
Step 3: Standardize telemetry early
We implemented consistent logging and metrics across apps (request IDs, user/workspace IDs, error taxonomy). This sounds boring, but it prevented platform work from becoming guesswork.
Practical example: once every service logged workspace_id consistently, we could answer "which customers are hitting rate limits?" in minutes instead of days.
Step 4: Gradually move shared capabilities behind APIs
Instead of rewriting Product B to match Product A, we extracted shared capabilities only when there was clear duplication.
For instance:
- A shared "files" service (uploads, virus scan, signed URLs)
- A shared "notifications" service (email templates, rate limiting, unsubscribe handling)
Each extraction had a cost justification: "This removes X lines of duplicated code and Y hours of on-call noise per month."
Cost-saving tactic: we resisted building a generic internal framework. Whenever we felt tempted to make something "configurable for all future needs," we shipped a version that solved the next two known use cases and left extension points for later.
The Money-Saving Playbook: What Actually Kept Us Under Budget
Here's what made the difference between a sensible platform and an expensive science project.
1) Define platform ROI in concrete terms
We tracked four metrics:
- Support tickets related to access/login
- Time to ship an integration (from kickoff to production)
- Onboarding time for a new customer workspace
- Duplicate code hotspots (measured in "number of implementations" rather than lines)
If a platform effort didn't move one of those, it was a "nice to have."
2) Buy before you build (but only for commodity pieces)
We paid for managed services where the alternative was years of maintenance:
- Managed identity provider
- Managed database backups
- Hosted observability
But we avoided paying for tools that didn't match our workflows. For example, instead of buying a heavy integration suite, we standardized on webhooks + events + a connector library first.
3) Keep data ownership clear
Unified platforms fail when nobody knows what system "owns" a field.
We set a simple rule:
- Platform core owns identity, workspace, entitlements
- Each product owns its domain entities
- Analytics reads from both but doesn't redefine truth
That let teams move faster without stepping on each other.
4) Adopt a "paved road," not a mandate
We created blessed defaults (libraries, templates, CI checks), but we didn't force every team to migrate instantly.
If a product team used the platform auth library and standard logging, they got:
- faster security reviews
- less on-call debugging
- built-in dashboards
Migration became attractive, not painful.
5) Make the platform team small and service-oriented
A big platform team can accidentally create big-platform problems.
We kept it lean and measured success by:
- enabling product teams
- reducing lead time
- improving reliability
Not by "number of services built."
What we'd do again (and what we'd avoid)
Do again:
- Ship a unified shell early for immediate customer impact
- Standardize identity, workspace, entitlements first
- Invest in observability before major migrations
Avoid:
- Over-designing permissions before real customer demand
- Building a generic "integration platform" too early
- Migrating all data into one database "for simplicity"
If you're trying to unify products without a blank check, start with a thin platform core, unify the customer-facing seams first, and measure savings in support load and engineering duplication-not in how pretty the architecture diagram looks.
Related Reading:
* How a Single Whisper Changed How My AI 'Understood' My Boss (And You Can Too)
* Use appropriate scales and axes to accurately represent the data, and avoid distorting the data or misrepresenting it in any way.
* The Power of Big Data in Fintech: How Analytics is Changing the Financial Landscape
* A Hubspot (CRM) Alternative | Gato CRM
* A Trello Alternative | Gato Kanban
* A Slides or Powerpoint Alternative | Gato Slide
* My own analytics automation application
* A Quickbooks Alternative | Gato invoice
* Data Warehousing Consulting Services In Austin Texas
* Data Visualization Consulting Services Austin Texas
* Nodejs Consulting Services
* Data Engineering Consulting Services Austin Texas
* Advanced Analytics Consulting Services Texas
Powered by AICA & GATO
Curious about an Austin software development and consulting group? See what dev3lop.com has to offer.
Comments
Post a Comment