Posted 2026-07-15 · Coverly Team, Engineering
Product

Inside the multi-carrier quote engine: live APIs, simulated fills, and how we keep p95 under 90 seconds

A walkthrough of the carrier connector layer — base abstraction, the AIG proof-of-concept, staggered fallbacks, and why simulated quotes still beat the manual alternative.

The hardest part of building a multi-carrier quote engine is not calling carriers. It is reliably returning a useful comparison to the consumer in under ninety seconds when half the carriers you want to talk to will not answer you in time. This post is a walkthrough of how the Coverly quote engine is structured, what each layer does, and where we have been forced into tradeoffs that we did not anticipate when we started.

The shape of the problem

A consumer submits a form with vehicle year / make / model / ZIP plus driver age and license status. The engine needs to return three to five carrier quotes, sorted by monthly premium, with a recommendation, in under ninety seconds. Carriers respond on very different timelines. AIG's API will answer in two seconds; a small MGA might take forty-five. Some carriers have no public API at all, and the only way to get a rate is to call them.

We serial mode was not viable — that pushed our p95 above three minutes. We tried fan-out-and-wait, but a single slow carrier blocked the whole response. We ended up at a layered, time-boxed fan-out with a sim fallback at the tail. That shape has held for nine months and counting.

The connector layer

Every carrier — live or simulated — is an implementation of the same abstract class. The class has four responsibilities: shape the inbound request into the carrier's preferred format, send the request over the carrier's transport (HTTPS, SFTP, polling), parse the response back into a Coverly-normalized quote record, and report a structured error if any of those steps fail.

The abstract class is BaseCarrierConnector in lib/carrier-api/base.js. Every live and simulated connector extends it and overrides exactly the carrier-specific code. This means we can add a new carrier by writing one file that fits four methods, and the rest of the engine never has to know the difference.

The AIG proof-of-concept

AIG was our first live connector because their API is a clean HTTPS REST endpoint with structured inputs and outputs. The connector shape is: build a JSON body from the standardized lead form, send it to AIG with our partner credentials, parse the response back into a quote record, and stamp it with isLive: true. End-to-end this runs in 1.8 seconds median.

Lincoln Financial, Northwestern Mutual, and Pacific Life are currently stub connectors — the abstraction is real, the response comes from the simulator with a flag of isLive: false. Once we have partner credentials in place for each, the implementation swap is a single file change, no engine code touched.

Staggered fan-out with time budgets

When a quote request arrives, the engine fires every connector in parallel with a per-connector time budget. The default budget is eight seconds for live carriers, fifteen seconds for simulated ones (they have local table lookups so they should be faster, but we give them more headroom to be conservative). When the fastest carrier returns, the engine starts a "minimum set" timer; once we have at least three live or simulated quotes, we return the response immediately.

We do not wait for every carrier. We wait for the fastest majority. Every quote that lands after the response is sent is a "late fill" — it shows up in the partner dashboard but does not block the consumer experience.

This is the single most important architecture decision we made. The alternative — wait-for-all — produced a beautiful comparison on paper, but in practice meant that one slow carrier on a Tuesday afternoon pushes every consumer's response time past the threshold where they bounce. We would rather show three quotes in eight seconds than five quotes in forty-five.

Why simulated quotes still ship

People who evaluate us sometimes ask why we ship quotes that are not actually from the carrier. The answer is twofold:

  1. The consumer still benefits. A "good enough" comparison presented in under ninety seconds converts better than an "ideal" comparison presented in three minutes. We A/B'd this against an "all-live-wait" variant in our first quarter; the fast variant won on quote-to-bind by a wide margin.
  2. The broker-partner benefit clears the bar. Our partner-panel partners measure us on quote volume and lead-to-bound, not on whether every quote number was sourced from a real carrier API. The simulator's job is to surface an estimate good enough to set an anchor for the discussion; the real carrier rate flush comes on the back-end once a producer picks up the lead.

Every simulated quote is stamped with the word "est." in the UI, and every live quote is stamped with a "LIVE" badge. We have not had a single partner ask us to hide the distinction; concealing it would erode trust faster than it would sell quotes.

What is next

The roadmap is straightforward and unglamorous:

If you are a carrier API team reading this and your endpoint hasn't been integrated yet, the work is small — BaseCarrierConnector has four methods, our sandbox can replay real-form payloads at you, and your partner gets a new channel of inbound volume the same week.

Try the quote engine end-to-end.

Drop a vehicle into the form and watch three to five carriers return in under ninety seconds.

Start a Quote → For Brokers
Get Quote 90 seconds · no signup