/projects/kota-embed
← All projectsKota Embed
Health insurance enrollment, embedded inside other companies' platforms.
Senior Product Engineer, platform team · Professional work

Overview
Kota Embed lets employers offer health insurance to their employees without leaving the software they already use — the enrollment flow runs embedded in a third-party platform, backed by a multi-tenant .NET service that integrates directly with insurers.
What I did
I owned the multi-tenant core — the part that turns an enrollment request into a policy across nine insurers that each behave differently.
- The intent state machines behind enrollment, quoting, amendment and renewal.
- Adaptive requirements: asking a service what a case must collect instead of hardcoding a form per insurer.
- The versioned public API contract and its webhooks.
- Provider contracts introduced behind feature flags and migrated without stopping the product.
- Idempotency and duplicate suppression, and the integration suite that covers them.
The front end — the embedded flow and its SDK — was built by others; I have no commits in it.
The problem
Enrolling someone in health insurance looks like a form. It is not. Each insurer wants different data in a different shape on its own schedule; some answer over HTTP, others by exchanging files over SFTP. Regulatory disclosure obligations differ by region. And all of it happens inside an iframe hosted on another company’s platform, where the user expects it to feel immediate. A form hardcoded per insurer does not survive the second insurer.
By the numbers
Architecture
A .NET modular monolith split by bounded context: the multi-tenant platform core, one module per insurer, plus compliance, webhooks, and financial reporting. The core never calls an insurer directly — every provider call goes through an adapter factory, so the code that runs an enrollment does not know which insurer it is talking to. Long-running work is modeled as an intent: a persisted state machine rather than a request held open.
- Third-party platformThe host application, embedding the enrollment flow in an iframe.
- Public APIVersioned contract and signed webhooks for the platforms doing the embedding.
- Platform coreEmployers, employees, eligibility, and the intent state machines.
- Adapter factoryThe single door to every insurer, keeping the core provider-agnostic.
- Insurer integrationsOne module per insurer, over HTTP or scheduled SFTP file exchange.
The life of an enrollment
These are the statuses an enrollment actually moves through. It can also end ineligible, or not undertaken at all — the happy path below is not the only way out.
- ProcessingThe request is recorded against its idempotency key and validated, before anything external is called.
- ActionRequiredSomething is missing that only a person can supply. The intent says so and waits, instead of failing.
- PendingConfirmationEverything the insurer and the region require is gathered; the requester confirms before it is sent.
- EnrollingHanded to the insurer through its adapter, which answers on its own schedule.
- EnrolledThe policy exists. The platform reports it back to whoever asked.
What it does
- Multi-tenant by construction: platform → employer → employee → group, isolated per tenant.
- Group setup, enrollment, quoting, amendment, renewal, policy import, and dependant management, each as its own workflow.
- Eligibility computed from provider rules rather than stored as a flag.
- Policy and plan data aggregated across insurers into a single response.
- A versioned public API and signed webhooks for the platforms doing the embedding.
- Insurer integrations over both HTTP APIs and scheduled SFTP file exchange.
Engineering decisions
Intents instead of request/response
An enrollment cannot finish inside one call — an insurer may take minutes or days. Modeling it as a persisted state machine with its own status makes the in-between state something the system can query, resume, and report on, instead of a transaction held open and hoped for.
Adaptive requirements instead of a form per insurer
What a given case must collect depends on the insurer and the regulatory region at once. Rather than encoding nine forms, the platform asks a requirements service what this case needs and renders that. Adding an insurer stops being a front-end change. The lookup happens behind the same adapter boundary, so the core still never handles a provider identity itself.
An adapter factory as the only door to a provider
The platform core resolves an adapter and talks to that. It never learns which insurer it is serving, which is what keeps a tenth integration from touching enrollment logic — and what let provider contracts be introduced behind feature flags and migrated without stopping the product.
Idempotency and duplicate suppression as a requirement, not a repair
Retries happen, webhooks arrive twice, and consumers run concurrently against the same rows. Intent creation takes an idempotency key, auto-enrollment suppresses the duplicate intent-and-webhook pair, and the eligibility-screening consumer handles serialization conflicts rather than assuming they cannot happen.