Skip to content
Work/Case Study
External Integration · Data Modelling

Integrating sixty systems you don't control

Some expose an API, some only a database, each with its own idea of reality — mapped onto one model. This is a case study about restraint: the abstraction I refused to build until the real cases forced my hand.

Role
Canonical model + per-vendor adapters; primary author of the hardest vertical
Domain
Dental · optometry · chiropractic · orthodontics
Timeframe
2023 → 2026
Headline result
~60 systems · 4 verticals · one model
OwnershipImplementation · HighDesign · HighTech Leadership · MediumOperational · HighConfidence · High
01 — Background

Our platform schedules appointments, but it doesn't own the source of truth — the clinics do, through the practice-management systems they already run. To be useful, the platform has to stay in sync with roughly sixty of those external systems and make them all look the same to the rest of the product.

These systems agree on almost nothing. Some expose a clean API; some only a database you read directly; many run on-premise, reached across a network. And the moment we grew past dental into optometry, chiropractic, and orthodontics, each new vertical broke an assumption the dental-shaped core had quietly baked in.

Protect the interior.
Let the exterior stay chaos.

02 — Problem

Dental-only, integration was contained: one canonical notion of appointment, provider, and operatory (the room or chair), with each vendor mapped onto that shape. The invariant that held it together was the most important decision in the system —

An appointment stays an appointment; a patient stays a patient. No per-vendor database changes. Ever.

The design that works for two vendors strains at ten. By the time you're contemplating dozens across four verticals, the naive paths fail — and the tempting overcorrection (build the grand framework up front) is a trap, because you don't yet know the shape of the variability you're abstracting over.

Fig 1 · One model, absorbing the mess at the edge
system · API
system · database only
system · UI only
~60 external systems
adapters
Canonical model
appointment · provider
operatory · patient
the interior never changes shape
Scheduler + booking
never learns the vendor

variability is absorbed at the boundary — vendor quirks never leak inward

The adapter's only job is translation: whatever the vendor's reality, produce canonical shapes. Downstream stays simple because the boundary does the suffering.
03 — Reading the divergence

There's no profiler for this. The work was understanding, vertical by vertical, how each one differs from the canonical model and why. Two findings shaped everything — and they're two separate axes I kept apart in my head.

Fig 2 · Divergence clusters by vertical — that's where the seam is
Dentalthe baseline — providers, operatories, hours
Optometryno operatories at all — the room-per-appointment concept simply doesn't exist
Chiropracticoptional rooms · multi-appointment-type · multi-day appointments
Orthodonticsno hours given — a different representation that must be derived into hours
second axis · access surfaceAPIdatabase onlyUI only
Two clean axes beat one tangled one: what it maps to (vertical) and how you reach it (access surface). The clustering told me the eventual seam was per-vertical, not per-vendor.

And the maintenance pain was itself the signal. As vendor-specific conditions accumulated, the sync paths got harder to reason about. That accumulating friction was the data point I'd been waiting for — the branching had done its job; it was finally time to abstract.

04 — Alternatives considered

Rejecting the second one is the senior move — not building it.

Per-vendor bespoke code, no shared model

Rejected

Short-term velocity, long-term paralysis. Nothing reusable; a shared-behaviour change means touching N places. Doesn't survive past a handful of vendors.

A universal framework, designed up front

Rejected

It feels like senior engineering; it's usually a mistake. You can't design the right abstraction before real cases teach you what varies. Optometry alone would have shattered a dental-shaped framework's "every appointment has a room."

Change the core model per vendor

Never

The tempting shortcut under deadline: "just add a vendor-specific field to the appointment." Every time, you leak exterior chaos into the interior and pay for it forever.

Canonical model + branch now, extract later

Chosen

Keep the stable interior, absorb variability at the edges, duplicate-and-adapt when a divergence is too large to branch inline — and wait to build the reusable abstraction until the patterns are undeniable.

05 — Decision

A discipline, more than a diagram — four commitments, held in sequence.

1

One canonical model, defended

A single internal shape every vendor maps onto. The interior never changes shape because a vendor is weird.

2

Adapters keyed to the access surface

Meet each system where it lives — API adapter, direct-database adapter — whose only job is to produce canonical shapes.

3

Variability isolated at the edges

Contained conditions — the missing-operatory guard, optional rooms — never smeared through shared code. When a divergence is large, duplicate-and-adapt rather than contort a shared path with if vendor == ….

4

The abstraction, extracted when earned

Once the per-vertical clustering was undeniable and the branching hurt, I built the extensible per-vertical engine on our newer platform — the framework came after the patterns, shaped by real cases, not before them.

Don't build the framework
until the real cases demand it.

06 — Architecture: the sequence

The legacy branching wasn't debt to clean up. It was the phase that taught me the abstraction.

Branch-then-abstract, read as a timeline. Each stage was correct for its moment — the mistake would have been skipping straight to the end.

Fig 3 · Branch → duplicate → feel the pain → extract
1 — 2 vendors
Special-case

Branch per vendor. The right place to start.

10+ vendors
Duplicate & adapt

Conditions accumulate across verticals.

the signal
Friction hurts

Maintenance pain = permission to abstract.

earned
Per-vertical engine

Each vertical a clean strategy, not a pile of conditions.

the abstraction you build in the abstract is almost never the one the real cases need

Precise boundary: for orthodontics, the derivation of hours on the vendor-database side was another team's work. What I built was the on-our-side adapter that invokes it and maps the result into the canonical model.
07 — Trade-offs
Chose

Deliberate, temporary debt

Not buying
A clean framework up front. Branch-and-duplicate accretes conditions — real debt, taken consciously and paid down once the shape was clear.
Chose

Read a vendor's DB directly

Not buying
API-contract stability. Where a system offered nothing else, direct-DB works — but it's brittle to a schema change. I accept that risk clear-eyed.
Chose

Hold the canonical line

Not buying
Surfacing every vendor's pet concept. Sometimes a useful idea doesn't map cleanly; I find a faithful mapping or don't surface it, rather than fragment the interior.

Being precise about ownership is part of the trade too: the largest integration I authored is the chiropractic vertical — the most divergent from the dental baseline — and the orthodontics adapter, whose hours-derivation on the vendor side belonged to another team.

08 — Outcome
measured in reach & stability, not milliseconds
~0

External systems integrated onto a single canonical model — API, database, or UI, all made to look the same inside.

reach
0 new

Clinical verticals brought onto a dental-only platform — three new markets the business could sell into, with no per-vendor change to the core model.

market
0

Times the interior fragmented. After dozens of integrations across four verticals, an appointment is still an appointment — the non-event that is the whole return.

stability
09 — Lessons learned
Protect the interior at all costs. Refusing to change the core model per vendor was the highest-leverage decision. Every bit of exterior chaos kept out is a change you never make in a hundred places.
Let the surface dictate the adapter, the domain dictate the mapping. Keeping "how do I reach it" separate from "what does it map to" kept a messy problem tractable.
Don't abstract on speculation. The right abstraction is the one the real cases hand you. Branch, duplicate, learn, then extract — the optometry vertical alone would have blown up a framework designed from dental.
Duplication is sometimes the honest choice. A bounded, deliberate duplicate often beats a shared function contorted by vendor conditionals. Reach for the abstraction when the pattern is clear, not when the linter feels offended.
Be precise about the boundaries of your work. The vendor-side derivation wasn't mine; the adapter was. Saying so exactly is what makes the rest of the claims credible.
10 — If I rebuilt this today

The core approach I'd repeat exactly. Three things I'd finish.

Change

Formalize the adapter contract

The abstraction has been earned — so the per-vertical engine should become the only way integrations are written, and the remaining in-line branching migrated onto it. The job now is to finish collecting the dividend.

Learned

Per-vendor integration-health monitoring

Sixty external systems, many on-premise, are sixty things that can quietly break. A per-vendor sync-health dashboard turns "a client noticed their appointments stopped syncing" into "we noticed first."

Change

Shrink the direct-database surface

Where a vendor now offers an API it didn't before, migrating off direct-DB trades brittleness for a stable contract. Unglamorous — but reducing what can break out from under you is real reliability work.

© 2026 Sukhcharan SinghCase study · Integrating sixty systems you don't control