SLA vs SLO: What They Mean for Carrier APIs
SLA vs SLO explained for carrier integration platforms: what each term promises, how error budgets work, and how to calculate composite uptime.
An SLA is the external, contractual uptime or performance promise a platform makes to a customer, with financial consequences attached. An SLO is the stricter internal target engineering actually builds and alerts against. An SLI is the measured number that proves which one, if either, you're hitting right now. If you run carrier middleware and you've only ever used these three words loosely in a sales deck, this is the post that pins them down.
The three terms, defined in one pass
Start with the hierarchy, because it's the part people get backwards. SLAs, SLOs, and SLIs form a hierarchy: an SLA can contain several SLOs, and each SLO depends on one or more SLIs for measurement. In plain terms: the SLA is what you signed with the shipper. The SLO is what your platform team actually targets, day to day, so that the SLA never gets close to being tested. The SLI is the live telemetry that tells you where you stand against both.
A cleaner way to separate SLA from SLO, if the hierarchy framing doesn't click immediately: a service level agreement (SLA), a service level objective (SLO), and a service level indicator (SLI) sit at three different layers of the same reliability system. The SLI is what you measure, the SLO is the target you hold that measurement to, and the SLA is the promise you make to a customer with money attached to it. The SLO has to sit strictly inside the SLA, with room to spare. Your SLA should always be looser than your SLO, and your SLO is only as trustworthy as the SLI feeding it.
Why does the gap matter? Because the gap is your working room. When an SLO falls below target, the team should investigate and respond before the SLA is breached. The SLI is the evidence that shows whether the SLO is still on track. No gap, no warning. You find out about trouble the same moment your shipper does, usually via an angry ticket.
Why these get confused in carrier integration specifically
Here's where generic SRE explainers stop being useful and carrier middleware gets genuinely harder. You're not managing one SLA. You're managing at least two, and they're not the same contract with the same party.
There's the carrier's own published uptime (DHL's, UPS's, PostNL's, FedEx's), and there's your platform's SLA to the shipper tenant sitting on top of your integration. These are two completely separate agreements, with separate signatories, and conflating them is the single most common mistake in this space. If DHL's status page says 99.9%, that number describes DHL's liability to you, not your liability to your customer. Nothing stops you from quoting a tighter or looser number to your own tenants, but whatever you quote, it has to survive DHL having a bad day.
Each carrier also has its own failure signature, and a single "uptime" number hides all of it. FedEx schedules regular maintenance windows that can block API access for several hours, while UPS rate limits spike unpredictably during peak shipping periods. DHL's XML validation has become increasingly strict, rejecting requests that worked fine last month. None of that shows up cleanly in a single composite uptime figure, but it all eats into your error budget the same way a hard outage does.
Negotiated terms compound the mess. Large retailers might have negotiated SLAs requiring 99.9% uptime, while smaller shippers accept 99.5%, which means the same platform can owe genuinely different SLAs to different tenants simultaneously. The monitoring needs to track these negotiated SLAs per carrier, not generic uptime metrics. A single dashboard showing "platform uptime: 99.95%" is nearly meaningless when tenant A's contract and tenant B's contract reference different thresholds entirely.
Worked example: composite uptime across three carrier dependencies
This is the maths that actually matters, and it's simpler than most people expect, which is exactly why it gets skipped.
Composite availability across independent dependencies is multiplicative, not additive. Composite SLA = SLA₁ × SLA₂ × SLA₃ × ... Chain three carrier dependencies and the formula does the damage for you: 0.9999 × 0.9999 × 0.999 = 0.9988 = 99.88%.
Translate that into something you can defend in a contract negotiation. 99.9% uptime means a service can be down for up to 8 hours and 46 minutes per year, or about 43 minutes per month, and this is the most common SLA tier for production APIs. The common "nines" reference points, in monthly downtime:
- 99% uptime: 7 hours 18 minutes of downtime per month, or 3.65 days per year
- 99.5% uptime: roughly 3.6 hours of downtime per month
- 99.9% uptime: 43.8 minutes of downtime per month, or 8.76 hours per year
- 99.95% uptime: approximately 21.6 minutes of downtime per month
- 99.99% uptime: 4.38 minutes of downtime per month, or 52.6 minutes per year
Now suppose your middleware depends on DHL, PostNL and a regional LTL carrier, and two of those sit at 99.99% while the weakest (the regional carrier, predictably) sits at 99.9%. Run the formula and you land at 99.88% composite availability, not 99.9%, let alone whatever tighter number sales promised. Promising 99.95% to a shipper while sitting on top of three 99.9% carrier dependencies isn't an aspirational target. It's a maths error, because compound SLAs: multiply each service's uptime — two 99.9% services yield only 99.8% overall, a loss of 86 minutes/month. Add a third dependency and it only gets worse.
Where the error budget actually comes from
This is the detail that trips up teams who've read the SRE books but haven't applied them to a multi-carrier stack: the error budget is derived from the SLO, never from the SLA. You cannot build a meaningful operational budget out of a legal document.
The calculation itself is almost embarrassingly simple. Error Budget = 100% − SLO. A 99.9% SLO gives you a 0.1% error budget, which in minutes works out to 43.2 minutes of downtime allowed per 30 days, calculated directly from the time window in minutes times (1 minus the SLO target).
What a platform team does with that budget is the operational payoff. Spend it carefully: when burn rate spikes (meaning the budget is being consumed faster than the measurement window allows), freeze risky carrier-adapter deploys and investigate. The error budget is the failure allowance, the inverse of your SLO. A 99.9% SLO = 0.1% error budget = 43 minutes of downtime per month. When the budget is healthy, ship freely, including the adapter changes you've been sitting on because you were nervous about DHL's XML validation flagging something new.
Common mistakes platforms make with SLA/SLO wording
A short list of the ones that show up repeatedly in carrier middleware specifically:
- Quoting a carrier's advertised uptime figure as if it were the platform's own SLA to tenants, when it's someone else's contract entirely.
- Setting the internal SLO equal to the external SLA, leaving zero room to absorb a carrier incident before breaching the shipper contract.
- Measuring "platform uptime" as one aggregate number instead of the per-tenant, per-carrier SLI that shippers actually feel — a DHL label-generation failure affecting one tenant isn't "the platform is down," but it's exactly what that tenant will report as an outage.
- Publishing a single clean uptime number without stating which carrier dependencies, and how many, sit underneath it.
Platforms in this space, MercuryGate, Descartes, nShift, FreightPOP and Cargoson among them, each publish their own SLA language to shippers. None of that language tells you how many carrier dependencies sit underneath the number, which is exactly the gap the composite maths above is built to close. Read any published SLA with that question in mind before you take the headline percentage at face value.
FAQ
Is a 99.9% SLA good enough for carrier integration? It depends entirely on how many upstream carrier dependencies are chained underneath it. A single-carrier integration at 99.9% is a reasonable commitment. The same 99.9% promised on top of three chained 99.9% carrier dependencies is mathematically impossible to sustain, per the composite formula above.
Does a carrier's SLA breach excuse your own SLA to the shipper? No. The two contracts are entirely separate. Your error budget has to be sized to absorb known carrier flakiness (maintenance windows, rate-limit spikes, validation changes) before it ever reaches the shipper-facing SLA.
Can you have an SLO without an SLA? Yes, and many engineering teams do exactly this. An SLO is a reliability target for a specific service metric: the internal bar a team holds itself to, whether or not a formal SLA exists. Internal services and early-stage platforms frequently run SLOs with no external contract attached at all.
How often should carrier-dependent SLOs be recalculated? After every new carrier onboarded. Each additional dependency adds a multiplicative term to the composite formula, and a single new regional carrier at a weaker published tier can quietly drag the whole composite number down even if every existing dependency is unchanged.