Skip to content

SYSTEM Cited by 1 source

fast_page gem

What it is

fast_page is a PlanetScale-authored Ruby gem that applies the MySQL deferred-join optimisation to ActiveRecord::Relation objects via a single .fast_page method:

Post.all.order(created_at: :desc).limit(25).offset(100)
# Post Load (1228.7ms) — slow baseline

Post.all.order(created_at: :desc).limit(25).offset(100).fast_page
# Post Pluck (456.9ms) + Post Load (0.4ms) — 2.7× faster

Introduced in Mike Coutermarsh's 2022-08-16 PlanetScale blog post, the gem is a direct Ruby port of Caleb Porzio / Aaron Francis's Laravel equivalent, hammerstonedev/fast-paginate (also 2022). Both gems are packaged implementations of the deferred-join technique documented in High Performance MySQL.

(Source: sources/2026-04-21-planetscale-introducing-fastpage-faster-offset-pagination-for-rails-apps.)

What it does

Mechanically, .fast_page rewrites a .order(…).limit(N).offset(M) chain into two SQL queries:

  1. Index-only primary-key pluck: SELECT id FROM t ORDER BY … LIMIT N OFFSET M.
  2. Hydrate by primary key: SELECT * FROM t WHERE id IN (…) ORDER BY ….

The database does M + N index-only leaf walks and only N clustered-index descents — instead of M + N clustered-index descents in the baseline. For wide SELECT * at deep offsets this collapses the dominant cost.

Scope and non-scope

Scope — what the gem is: - A narrow query-rewriter for ActiveRecord::Relation objects using offset / limit. - A bridge to the deferred- join-for-offset-pagination pattern that doesn't require developers to hand-write the SQL. - An application-tier library — runs in the Rails client process, not in the database or proxy.

Non-scope — what the gem isn't: - Not part of the PlanetScale database product; works against any MySQL instance (RDS, Aurora, self-hosted, PlanetScale). - Not a cursor-pagination implementation. It preserves offset semantics (you can still GOTO PAGE 47); cursor pagination is the separately-named alternative for next/previous-only UX. - Not a planner hint or SQL extension. Pure Ruby-level query rewriting.

Operational guidance (from the post)

  • Apply conditionally past page N. The gem runs two queries instead of one, so it's slower for shallow pages. Canonical usage:
    posts = Post.all.page(params[:page]).per(25)
    posts = posts.fast_page if params[:page] > 5
    
    See patterns/conditional-optimization-by-page-depth.
  • Benchmark on your own data. Coutermarsh's > 5 is a starting heuristic; the correct crossover depends on row width, network RTT, and data distribution.
  • Requires ORDER BY. Without one, the first query has no index to prefer and the optimisation's premise collapses.
  • Benefits scale with page depth. For shallow apps (OFFSET always < 100) the wins are modest; for deep pagination (OFFSET > 10k) the wins are dramatic.

Place in PlanetScale's Ruby ecosystem

fast_page is one of several PlanetScale-authored Ruby gems surfacing in wiki sources:

All three are application-tier tooling written by PlanetScale's Rails team against their internal Rails monolith, not database-product components. They canonicalise a pattern the wiki sees often in PlanetScale sources: the company's Rails engineers packaging internal operational fixes as open-source gems.

Scope the source does not cover

  • Gem internals — the post shows the user-facing API but not the implementation (how .fast_page is attached to ActiveRecord::Relation, which ActiveRecord versions are supported, whether it handles edge cases like includes / joins / select chains).
  • Cross-database support — the post benchmarks on MySQL only. The deferred-join technique works on PostgreSQL too, but it's unclear whether fast_page produces Postgres-compatible SQL out of the box (the gem name and blog framing are MySQL-specific).
  • Performance at extreme offsets (OFFSET > 100k) — benchmark stops at ~2000 pages × 100 per page = ~200k.
  • Production-deployment experience at PlanetScale — no disclosure of which PlanetScale application queries adopted .fast_page, what crossover threshold they settled on, or incident counts before / after.
  • Interaction with Vitess — PlanetScale's own product uses Vitess as the MySQL proxy; whether fast_page's two-query pattern interacts with VTGate's query planner, buffering, or cross-shard execution is not discussed (the Rails app in the post connects directly to MySQL, not to a VTGate).

Seen in

  • sources/2026-04-21-planetscale-introducing-fastpage-faster-offset-pagination-for-rails-appscanonical wiki source. Mike Coutermarsh's introduction of the gem. 2.7× benchmark at offset 100 on a 1M-row table; 2000-page sweep chart; explicit cross-ecosystem credit to Hammerstone's Laravel port and Aaron Francis's blog post Efficient Pagination Using Deferred Joins. Author's byline: Mike Coutermarsh, PlanetScale Rails-team engineer — his fourth wiki ingest after 2022-01-18 (Rails CI), 2022-02-17 (self-healing Sidekiq), 2022-06-29 (SQLCommenter in Rails), and 2024-04-04 (PlanetScale schema changes).
Last updated · 378 distilled / 1,213 read