Skip to content
All writing
Engineering8 min read

What a vendor-agnostic core cost us, and why we paid it

Betting on one provider is a bet on their roadmap, their pricing and their uptime. We took the harder path and would take it again.

Daniel Reyes

Principal Engineer

The fastest way to ship a platform is to pick one upstream provider and build directly against their SDK. Authentication, pagination, streaming and usage accounting all work the way one vendor decided they should work, and you write no abstraction at all. We did this for the first four months and it was the correct decision at the time.

It stopped being correct the week a customer asked whether they could run our product against infrastructure in their own tenancy, for reasons that had nothing to do with quality and everything to do with a data-residency clause in a contract they had already signed.

The abstraction that survived

Our first attempt at a provider interface tried to normalise everything and was abandoned in a fortnight. The differences between providers are not incidental details you can paper over; some of them are semantic. Transactional guarantees, ordering, and what exactly happens when a request half-succeeds are all genuinely different, and pretending otherwise moves the failure from a place you can see to a place you cannot.

What worked was a much thinner interface with an explicit capability model. The runtime asks what a provider can do and adapts, rather than assuming everyone can do everything and catching the exceptions.

interface Provider {
  capabilities: {
    batchWrites: boolean;
    consistency: "strong" | "read-after-write" | "eventual";
    maxPayloadBytes: number;
    supportsIdempotencyKey: boolean;
  };
  send(req: Request): AsyncIterable<Chunk>;
}

Three booleans and a number carry most of the weight. The runtime plans differently for a provider without idempotency keys — it deduplicates on our side, retries more conservatively, and records that it had to — instead of discovering the difference in production as a double write.

What it cost

  • Roughly six engineer-weeks up front, and a permanent tax of about a day per provider release.
  • A conformance suite of 340 cases that every provider has to pass before it is offered. This is the real cost and the real value.
  • Giving up a handful of provider-specific features that had no equivalent elsewhere. Two of those we later missed.

What it bought

Three things, and only the first was on the plan. Customers can run against infrastructure in their own account, which unblocked the residency conversation. We can move traffic between providers during an outage, which we have now done twice for reasons entirely outside our control. And when a materially cheaper option appeared for one specific workload, moving that workload was a configuration change rather than a project.

The abstraction was justified by portability and paid for itself in availability. We did not predict that and would not have built it for that reason.

Keep reading

  • Engineering

    A log is not an explanation

    A complete log tells you everything the system did and nothing about why it did it. The gap between those two is where the hard afternoons go.

Give the queue to the agents.

Connect one system, run a week in shadow mode, and look at the numbers. If they don't move, you've lost an afternoon.

Free for 14 days · No card required

Live demo of Vantis · see all five brands