Skip to content
All projects

GitHub · Case study

Rails Backend for Pull Requests

The Ruby on Rails side of pull requests, Code View, and repository pages inside the github.com monolith.

Illustration of a glowing red ruby on a dark platform, wired to code-review panels and a database stack.
Illustration1 / 5
Illustration. The other images are screenshots of real public pages.
Role
Senior Software Engineer: Ruby on Rails and GraphQL work behind the pull request and Code View front end.
Company
GitHub

Overview

Server-side work in GitHub’s Ruby on Rails monolith behind the pull request, Code View, and repository experiences: Rails controllers and models, the graphql-ruby schema the React front end queries, and the MySQL and Git data underneath.

Problem

GitHub.com has been a Rails monolith from the start; GitHub’s engineering blog describes nearly two million lines of code and more than 1,000 engineers working in it. Pull request and file pages combine repository metadata, permissions, review state, and Git contents, and they have to stay fast inside that shared codebase.

Architecture

Rails Backend for Pull Requests system designRails monolithReact front endPRs · Code ViewRails controllersRoutes · permissionsRails modelsActiveRecordMySQLRelational dataGraphQL APIgraphql-ruby schemaBatch loadersNo N+1 queriesAPI clientsApps · integrationsGit storageFile contents · diffspagequeryAPIloadresolveSQLbatchedblobs
RequestData read / writeMoving dots show which way data flows.
  1. React front end → Rails controllers: request, page
  2. React front end → GraphQL API: request, query
  3. API clients → GraphQL API: request, API
  4. Rails controllers → Rails models: request, load
  5. GraphQL API → Batch loaders: request, resolve
  6. Rails models ↔ MySQL: data read / write, SQL
  7. Batch loaders → MySQL: data read / write, batched
  8. Batch loaders ↔ Git storage: data read / write, blobs

What made it hard

  • Loading deeply nested pull request data without one query per record.
  • Keeping GraphQL fields shaped around what the React front end renders.
  • Combining Git file contents and diffs with relational data.
  • Shipping safely in a codebase that deploys many times a day.

Solution

Rails controllers serve the pages, and graphql-ruby types expose pull request and repository data to the React front end and to API clients. Batch loaders gather records in groups, so a nested query costs a handful of SQL round-trips instead of hundreds, while file contents and diffs come from Git storage. Changes go through the monolith’s tests and review like everyone else’s.

Skills used

  • Ruby
  • Ruby on Rails
  • GraphQL
  • graphql-ruby
  • MySQL
  • REST

Impact

  • Supplied the server-side data behind the React Code View and pull request experiences.
  • Kept nested GraphQL reads batched rather than one query per record.
  • Worked within the shared monolith’s conventions, tests, and frequent deploys.

Decisions

  1. 01Batch data loading in one place instead of in every caller.
  2. 02Shape the schema around what the front end actually renders.
  3. 03Keep changes small and reviewable in a monolith that deploys many times a day.