A 48,000-line SDK, reduced to 10

@octokit/rest, the official JavaScript SDK for GitHub's REST APIs, wasn't initially a GitHub project. In 2017, GitHub's @bkeepers adopted the then-most-popular community package, github, to serve as the foundation. That package had deep roots: its first commit dates to June 2010, from the era of Node v0.1, before package.json even existed.

When maintainer Gregor Martynus took over in September 2017, the codebase stood at roughly 16,000 lines of code across three JavaScript files, a single large JSON file, and separate TypeScript and Flow definitions. By the time the rewrite concluded with version 17, the core of @octokit/rest had been whittled down to just 10 lines of code.

The maintenance bottleneck

The original architecture centered on a manually maintained routes.json file—nearly 8,000 lines defining every GitHub REST API endpoint. Because it was updated by hand, endpoints only appeared once someone noticed a gap or error. To solve this, Martynus built a script that scraped GitHub's REST API documentation nightly and generated a machine-readable JSON representation in the octokit/routes repository. Any detected changes triggered an automated pull request to @octokit/rest, followed by an automatic release. The generated routes.json eventually grew to 10,275 lines, with accompanying TypeScript definitions exceeding 26,700 lines—but now with guaranteed completeness.

Decomposing the monolith

With maintainability addressed, the focus shifted to decomposability. The Octokit JavaScript libraries serve all JavaScript runtimes, some with strict size constraints for browser bundles. Rather than a monolithic library bundling every endpoint, authentication strategy, and best practice, users needed the ability to assemble only the components they required.

The refactoring effort produced several standalone modules:

  • @octokit/endpoint: converts REST endpoint options into generic HTTP request options
  • @octokit/request: sends parameterized requests with sensible defaults across browsers and Node
  • before-after-hook: provides the API for hooking into the request lifecycle

By November 2018, version 16 introduced a plugin API, with most internal functionality moved into plugins that could later be extracted. A subsequent effort produced @octokit/core, a clean-room implementation free of deprecated code, along with separate packages for each authentication strategy.

From there, the remaining plugins were isolated:

  • @octokit/plugin-rest-endpoint-methods
  • @octokit/plugin-paginate-rest
  • @octokit/plugin-request-log

The validation plugin became unnecessary—TypeScript's compile-time checks eliminated the need for runtime request parameter validation, substantially reducing both code volume and bundle size. For instance, the previous definition for octokit.checks.create() spanned many lines; the version 17 equivalent is a fraction of that.

With all pieces extracted and refined, the final assembly of @octokit/rest itself collapsed to the promised 10 lines—simply wiring together @octokit/core and its three plugins.

Testing the transition

Every line changed between versions 16 and 17. To guard against regressions, Martynus worked from usage examples when he first adopted the project—no tests existed—and converted them into integration tests. He also created octokit/fixtures, a language-agnostic set of automatically updated HTTP mocks shared across the broader SDK ecosystem. Through additional integration tests, @octokit/rest reached 100% coverage, a threshold enforced on every subsequent change.

During the migration, version 16 tests were run against version 17, minus those covering deprecated APIs. After passing, the suite was trimmed: tests belonging to plugins, @octokit/core, or @octokit/request were moved to their respective packages. What remains are a few smoke tests and scenario tests backed by @octokit/fixtures.

What v17 delivers

With version 17, @octokit/rest no longer attempts to be the monolithic Node.js client. Instead, it's the JavaScript library that assembles all best practices—pagination, throttling, automated retries, support for every current and future authentication strategy, and even GraphQL requests via @octokit/core—while letting users opt into lighter-weight building blocks when they need them.