Skip to content

Architecture

InsureFlow is split into two deployment planes, and almost everything else about the platform follows from that split. Read this before the pages on tenancy, regions and documents, because each of them is a consequence of it.

The control plane holds reference data that every market shares: distribution channels, the product catalogue, and the rules that decide which insurer handles a given request. It is deployed once, in Singapore, and every market reads from it.

The data plane holds the transactional work: issuing coverage, the ledger, the event stream. It is deployed once per market, so Vietnam, the Philippines and Indonesia each run their own.

The split exists because those two kinds of data have opposite requirements. A product definition should be identical in every market and is expensive to keep in sync if it is copied. A policyholder record should never leave the country it was created in. One deployment cannot satisfy both, so the platform stops pretending it can and separates them physically. What that means for personal data specifically is in Regions and data residency.

ServicePlaneOwns
ChannelControl, SingaporeDistribution partner reference data
ProductControl, SingaporeThe insurance product catalogue, its items, attributes and lifecycles
RoutingControl, SingaporeWhich insurer handles a request, by product, channel and market
CoverageData, per marketCoverage issuance: validate, resolve, issue to the insurer, persist, publish
LedgerData, per marketThe financial ledger of premium transactions
ReportRead-only, SingaporeCross-plane aggregation for dashboards. Holds no database

Six, and the count is deliberate. Each one owns a decision that changes for a different reason: who distributes, what is sold, which carrier takes the risk, what was issued, what is owed, and what the whole thing looks like from above. A service that owned two of those would have to be redeployed when either changed.

Routing is the one that surprises people, because it looks like a lookup table rather than a service. It is not. Which insurer takes a given request depends on the product, the channel, the market and the commercial agreement behind them, all four of which move independently and none of which the coverage service should know about. Putting that decision behind an interface is what lets a carrier be added to a live market without touching the path a policy is issued on.

Every service owns exactly one database, and no service reads another service’s tables. If the coverage service needs a product, it calls the product service over HTTP and sees only what that API returns.

The cost is obvious: a single logical read becomes three network calls. The benefit is that adding a column to the product catalogue touches the product service and nothing else. Every other service is insulated from the change because it only ever saw an API response shape. On a platform that has to run the same product catalogue across three countries with different regulators, that isolation is worth more than the round trips it costs.

Service-to-service calls inside a request use HTTP. The coverage service resolves the channel, resolves the product, asks routing which insurer applies, and calls that insurer’s API to issue the policy. Each of those is a call the caller is waiting on, so each is synchronous.

Everything downstream of a successful issuance goes onto Kafka instead. Coverage publishes an event, and the ledger consumes it at its own pace. Accounting is not on the path between a rider opening an app and a certificate coming back, so it is not on the request either. It also means the ledger can replay the stream if it falls behind or needs to reprocess.

HTTP rather than gRPC or a shared database, because the boundary between two services should be a versioned contract that either side can evolve behind. A shared database makes every schema change a cross-team negotiation, which is the failure this design is built to avoid. That choice and what it costs are set out with the others under Design decisions.

The services speak the OPIN standard at their boundaries. The standard settles what a product, a coverage and a claim are, and the platform settles how they are deployed, separated and audited. Nothing on this page changes a definition the standard already made.

Insurer systems on the far side rarely speak it. Each one is reached through an adapter that translates, so a carrier’s own format never reaches the platform’s interior.

The standard is wider than any one deployment, and that is the design rather than a shortfall. It describes twelve modules so that an implementation anywhere can be read against one vocabulary. The services above are what this platform runs, and a tenant reaches the operations its own contract covers. So a module page documenting an operation is not a statement that your credentials can call it, and the two questions have different answers by design.

Check what you hold before you build against a module page. The surface issued to you comes with your credentials, on the same footing as the host and the scopes in Tenancy and scopes. If what you need is not in it, that is a commercial conversation rather than a technical one, and talk to us is the faster route than discovering it in integration.