SDK version drift: what happens after an API update ships

A practical guide to the gap between the SDK version a vendor ships and the version its customers run, measured across 32 vendors.
DefinitionSDK version drift is the distance between the version of a vendor's SDK that the vendor currently ships and the version its customers are actually running. It accumulates when every released change must be discovered, understood and applied separately by each customer.
78.6%
of live SDK traffic runs at least one major version behind
377
days old, at the median, is the version running in production
23/32
vendors where most live traffic sits on an outdated major

What SDK version drift actually is

Almost nothing your software does is written by you. Payments come from one vendor, email from another, authentication from a third, error tracking from a fourth. Each of those arrives as an SDK: a package you install once and then mostly forget about.

The vendor keeps working on it. New versions ship, old behaviour is retired, and occasionally something that used to work stops working. Your copy does not move. It sits at whatever version it was on the day someone installed it, until a person deliberately goes and changes it.

Version drift is the gap that opens between those two facts. It is measured in two different ways, and confusing them is the most common mistake in this whole subject:

A codebase can look fine on one measure and terrible on the other. That is not a hypothetical, and there is a table of it further down.

The measured gap: what 32 vendors show

In early August 2026 we measured 32 widely used vendors through the public npm registry: 355.7 million weekly installations spread across 7,190 distinct published versions. For each vendor we took the share of last week's downloads sitting on an older major than the current one, and the median age of the version being installed.

The worst end of the distribution is not close:

VendorPackage% a major behindMedian ageSlowest 10%
Google APIsgoogleapis100.0%699d1491d
Linear@linear/sdk99.7%208d825d
OpenAIopenai99.0%227d467d
DocuSigndocusign-esign98.1%707d1699d
Auth0auth097.0%270d1053d
Squaresquare96.4%591d747d
Pinecone@pinecone-database/pinecone95.8%467d1201d
Plaidplaid95.5%528d1020d

Google APIs sees literally none of its measured traffic on the current major. DocuSign's median install is 707 days old, and its slowest tenth is running code published over four and a half years ago. Across all 32 vendors, the worst single figure is a slowest-decile age of 1,893 days, which is five years and two months.

The pattern is that the older and larger the vendor, the further behind its customers sit. Newer vendors with smaller install bases look far healthier, and some of that is genuinely better release discipline, but a good deal of it is just that there has been less time for drift to accumulate.

The other end is more interesting than it first appears:

VendorPackage% a major behindMedian ageSlowest 10%
Supabase@supabase/supabase-js0.1%87d382d
Datadog@datadog/datadog-api-client0.0%413d1022d
Temporal@temporalio/client0.0%80d447d
AWS SDK@aws-sdk/client-s30.0%132d698d

Datadog scores a perfect zero on major-version lag while its median install is 413 days old. Nobody is behind, because the vendor has not shipped a new major for a long time. Everyone is still running year-old code. If your dashboard only tracks majors behind, that vendor looks green and is not.

The full report has all 32 rows, and every figure is linked to the public endpoint it came from.

Why teams fall behind

Drift is not simply neglect. It is the expected result when each customer must turn a vendor release into a change in its own codebase.

Upgrading an SDK competes with feature work, carries a risk of breaking working code, and often has no immediate customer-facing benefit. Release notes describe the required work, but they do not make the customer-specific change. So upgrades are commonly postponed until a deprecation or failure creates a deadline.

Compare it to servicing a boiler. Nobody schedules it because they are excited about it. They schedule it because the failure mode is bad enough and familiar enough to override the fact that nothing is visibly wrong today. Vendor SDKs have the same failure mode and none of the familiarity, so they do not get scheduled.

What version drift actually costs

To check whether any of this hurts, we searched public GitHub discussions for engineers describing vendor changes that broke something or forced an unplanned migration. Restricted to discussions opened since January 2024 and de-duplicated, that produced 1,234 distinct discussions from 767 different engineers. Thirty-one percent were still unresolved when the research was done.

Those are the cases visible enough to be written down in public. The costs land in three places:

Why the delivery model matters

Vendors do not create drift simply by improving their APIs. But when a release requires a customer-side change, the work has to travel from the vendor release process into every affected codebase. Across the 27 vendors whose release histories could be parsed cleanly, the median is 1.3 releases per year flagged for breaking-change language. The heaviest are far above that:

VendorBreaking releases/yrShare of releasesReleases sampled
Linear17.334.4%270
Sentry13.212.0%300
Twilio9.842.0%257
Shopify6.17.9%76
Stripe5.15.7%300
Temporal4.417.3%75

A mid-sized company with thirty vendor connections is therefore absorbing something on the order of forty breaking changes a year, arriving unannounced and unbatched, none of which it scheduled.

Self-audit: check your own SDK versions in an afternoon

The whole method above works on public data, which means it works on your data too. Here is the short version for a JavaScript project.

  1. Inventory what you actually have installed, not what the manifest asks for. package.json states a range; the lockfile and node_modules state a fact. Use npm ls --depth=0.
  2. Ask the registry when that exact version was published, and what the current version is. Both come from npm view <package> time dist-tags, which needs no authentication.
  3. Compute age and major-version lag per dependency.
  4. Rank by age, not by name. The oldest thing you depend on is the one most likely to surprise you.
  5. Treat anything over six months old or a major behind as debt, with a ticket and an owner. Not optional, not "when there's time".

That is thirty lines of Node, and it needs nothing but network access:

// sdk-age.mjs — how far behind is every direct dependency?
import { execFileSync } from 'node:child_process';

const sh = (args) =>
  execFileSync('npm', args, { encoding: 'utf8', stdio: ['ignore', 'pipe', 'ignore'] });

const tree = JSON.parse(sh(['ls', '--depth=0', '--json']));
const rows = [];

for (const [name, info] of Object.entries(tree.dependencies ?? {})) {
  const installed = info.version;
  if (!installed) continue;                       // unmet or linked
  let meta;
  try {
    meta = JSON.parse(sh(['view', name, 'time', 'dist-tags', '--json']));
  } catch {
    continue;                                     // private or unpublished
  }
  const published = meta.time?.[installed];
  const latest = meta['dist-tags']?.latest;
  if (!published || !latest) continue;
  rows.push({
    name,
    installed,
    latest,
    ageDays: Math.floor((Date.now() - Date.parse(published)) / 86400e3),
    majorsBehind: parseInt(latest, 10) - parseInt(installed, 10),
  });
}

rows.sort((a, b) => b.ageDays - a.ageDays);
for (const r of rows) {
  console.log(
    r.name.padEnd(34) + r.installed.padEnd(14) + r.latest.padEnd(14) +
    (r.ageDays + 'd').padEnd(10) + (r.majorsBehind > 0 ? r.majorsBehind + ' behind' : 'current'),
  );
}
const stale = rows.filter((r) => r.ageDays > 180 || r.majorsBehind > 0);
console.log(`\n${rows.length} direct dependencies, ${stale.length} over six months old or a major behind.`);

Run it with node sdk-age.mjs in any project with a node_modules. On a deliberately stale test project it prints:

package                           installed     latest        age       majors behind
stripe                            12.0.0        22.5.0        1223d     10 behind
openai                            4.0.0         7.4.0         1091d     3 behind
@slack/webhook                    7.0.0         8.0.0         1043d     1 behind

3 direct dependencies, 3 over six months old or a major behind.

If your own output has a line over 365 days, you are at the median of the 32 vendors measured here. That is not reassuring; it is the point of the research.

Common mistakes to avoid

  1. Trusting the lockfile. A lockfile guarantees the same version every install. That is its job. It is a record of what you froze, not evidence that what you froze is current.
  2. Measuring only majors behind. As the Datadog row above shows, a vendor that has not shipped a major in two years gives every one of its users a perfect score while they all run two-year-old code.
  3. Chasing latest blindly. Not every vendor confines breaking changes to majors. Some ship them in minors, which means "we only take minors automatically" is not the safety guarantee it sounds like.
  4. Ignoring transitive dependencies. The SDK you installed pulls its own. --depth=0 is the right place to start and the wrong place to stop.
  5. Counting CI as usage. Some registry download traffic is build runners re-pulling pinned versions rather than humans with a migration backlog. That inflates every ecosystem-wide number here, including ours, by an amount we cannot yet bound.

Why release notes are not enough

Dependency bots are useful for version updates, but a version bump is not the same as a migration. When an API changes, someone still has to understand the change, update the calling code and verify the result. Release notes explain that work; they do not deliver it to every affected customer repository.

This is the delivery gap behind integration drift. A Self-Maintaining API is an API that ships the customer migration with the release, so each customer can review and merge a relevant update instead of reconstructing it from scratch.

Frequently asked questions

How much vendor software runs an outdated version?

Across 32 major vendors measured in August 2026, the typical vendor sees 78.6% of its live traffic coming from customers running at least one major version behind. 23 of the 32 have most of their users behind, not a minority.

How old is the SDK code running in production?

The median installed version is 377 days old. The slowest tenth of users runs versions several years old, with the worst measured case at 1,893 days.

How often do vendors ship breaking SDK changes?

1.3 per year at the median across the 27 vendors whose release histories could be parsed cleanly. The heaviest ship more than a dozen a year.

Is anyone actually hurt by SDK version drift?

1,234 public GitHub discussions from 767 engineers document vendor changes that broke something or forced an unplanned migration. 31% were unresolved when the research was done.

How do I check whether my own SDKs are outdated?

Inventory installed versions, ask the registry when each was published and what is current, then rank by age. The script above does it in one command.

Why do release notes not solve version drift?

Release notes explain what changed, but each affected customer still needs to translate that information into a safe change in its own codebase. That work is easy to postpone until a deprecation or failure creates a deadline.

The research behind this page

32 vendors, measured through public npm registry download counts by version and the vendors' own published release histories. 355.7 million installations across 7,190 distinct versions. Collected 3 to 7 August 2026, so the live figures will have moved since: expect small drift, not different conclusions. No vendor was contacted, none participated, and none reviewed the findings before publication.

Every figure above is checkable. Sources and method lists each one against the endpoint it came from, and the dataset is published as CSV and JSON under CC0.

Download the full report (PDF)

Last updated 13 August 2026.