February 22, 2023·5 min read·engineeringrubyrubygemsdependenciescaching

RubyGems retires a dependency API built around uncached queries

The planned retirement of the dependency API shifts metadata access toward a cacheable compact index while preserving Bundler's fallback behavior.

A dependency API can save a client from downloading the entire package universe while creating a costly query workload for the server. That was a useful trade when Bundler needed selective metadata, but the request shape became a problem at RubyGems.org's scale. Most requests asked for a different combination of gems, limiting reuse through the cache.

The February 22 deprecation announcement says the dependency API accounts for twenty to twenty-five percent of traffic served by the Rails application that Fastly cannot cache. Each distinct gem list requires a complex database query. The planned replacement is not a new solver, but a metadata interface designed for caching.

I find Ruby code approachable, particularly when the language's consistent object model makes a larger application easier to follow. The infrastructure supporting that application also needs understandable costs. This deprecation identifies a concrete source of service work and a replacement designed to avoid it.

Selective requests solved an earlier problem

The endpoint accepts a comma-separated gems query parameter and returns dependency information in Marshal or JSON form. A request for Rails returns dependencies for every version of that gem. Bundler used this interface as its primary metadata source from version 1.1 until version 1.12 introduced the compact index in April 2016.

André Arko's 2014 account of the index redesign explains why selective requests originally mattered. Bundler's version solving required dependency information for multiple candidate versions. Downloading every specification for every package merely to resolve a small Gemfile was wasteful.

An index containing only the latest versions could not answer that problem. The newest version of one package might conflict with another requirement, forcing the resolver to consider older candidates. Efficient resolution therefore required access to historical dependency metadata without always downloading everything.

The dependency API answered that need by narrowing data to named gems. Its weakness lay on the server side. Arbitrary combinations of names create a much larger set of possible requests than a stable collection of per-package resources.

Query combinations defeat ordinary reuse

The February announcement says most requests include a unique gem list. Even when many clients depend on overlapping packages, their complete lists can differ. A response generated for one combination is not directly the response for another.

That means a cache in front of the service cannot eliminate the underlying query work as effectively as it can for stable resources. The announcement specifically identifies the traffic reaching the Rails application beyond Fastly's cache. This is a workload diagnosis, not merely a preference for a newer API.

The compact index changes the organization of metadata. The earlier design article describes plain-text resources generated when a gem is pushed, with client caching and incremental updates. Publication does work once that multiple readers can reuse.

This moves part of the cost from request-time combination to reusable metadata. A client can keep information it already fetched and ask for what changed. The design discussion describes ETags for checking changes and HTTP ranges for obtaining appended data.

Those details explain the reason for the architectural choice. The compact index is not simply a response with fewer characters. Its organization makes shared caching and incremental client updates part of the expected access pattern.

Fallback behavior limits the immediate effect

The deprecation announcement expects no visible effect for users of modern Bundler. Bundler tries the compact index first, then the dependency API, then the full index. Removing the middle option at RubyGems.org leaves the final fallback available.

Users of Bundler 1.11 or older may see slower installations. The announcement identifies these versions as predating compact-index support. They can still use the full index when the dependency endpoint is unavailable, but lose the selective interface that previously reduced their downloads.

That is a degradation in metadata acquisition rather than an assertion that every old client immediately stops resolving dependencies. The distinction matters when diagnosing a slower installation after an API change. A successful fallback may hide a major increase in downloaded information.

The announcement also distinguishes RubyGems.org from other gem sources. It says installations from repositories such as Gemstash, Geminabox, Nexus, Artifactory, and GitHub Packages will retain their existing behavior. Bundler's fallback sequence remains in place for those sources.

A proxy or direct API consumer still has a different integration contract from an ordinary Bundler invocation. Software that explicitly calls the retiring endpoint cannot assume that Bundler's fallback logic applies to its own requests.

Direct consumers need a metadata choice

RubyGems recommends that direct consumers move to the compact index or the Gem Version API, depending on which supplies the needed information. This is a question about data requirements. A dependency resolver and a program asking about one version do not necessarily need the same retrieval strategy.

The older index-design article also explains why metadata content matters. Version and platform information alone are not enough for all resolution decisions. Required Ruby and RubyGems versions and dependency constraints influence whether a candidate can be used.

A replacement integration therefore needs to preserve the information the consumer actually uses. Merely changing a URL without understanding that data model can exchange an explicit failure for an incomplete answer.

This is the part of the change I consider most useful for maintainers. It makes a long-standing operational dependency visible. A tool that fetches metadata directly owns the choice of interface and the interpretation of its response.

The announced schedule includes deliberate failures

As announced in February, the plan uses several brownouts before the final cutoff. March 22 has a five-minute outage at midnight UTC. March 29 has ten-minute outages at the top of every UTC hour. April 3 is an all-day outage, followed by planned removal from April 10 at midnight UTC.

During those periods, the endpoint is to return 404 responses. This exercises the absence of the API before the permanent change. A client relying on fallback should encounter its fallback path, while a direct integration can expose its dependence on the endpoint.

The schedule is a plan as of this announcement. The technical change is the retirement of request-specific database work in favor of metadata that clients and intermediaries can reuse. Bundler already has the compact-index path, and the planned brownouts provide a concrete way for less visible consumers to encounter the same transition.