SYSTEM
Ruby on Rails¶
Ruby on Rails is the dominant Ruby web-application framework (David Heinemeier Hansson, 2004). Canonical MVC web framework with ActiveRecord ORM, convention-over-configuration defaults, and a large ecosystem of companion gems for background jobs (Sidekiq), feature flags (Flipper), testing (Minitest / RSpec / FactoryBot), and SAML auth (ruby-saml).
Why it matters here¶
PlanetScale's application-tier backend is a Rails monolith. Multiple Rails-specific engineering posts have surfaced on the wiki:
- Rails
klass.underscoreconvention used as the stable key for feature-flagged job-enqueue rejection naming. - Rails test-suite parallelism (
parallelize(workers: N)) as the CI feedback-loop speedup lever. - FactoryBot factories as the fixture-library substrate + the object-explosion failure mode that goes with it.
Rails is also the substrate most SidekiqMiddleware::* code
lives in — client middleware runs inside Rails request
processes (or console sessions or rake tasks), server middleware
inside Sidekiq worker processes that boot the same Rails app.
Seen in¶
- —
canonical wiki introduction of Rails 7's
query_log_tagsnative feature + the ActiveRecordannotateper-query method + PlanetScale'sactiverecord-sql_commentergem that swaps the Rails-default tag format for SQLCommenter. Also surfaces the Marginalia gem as the Rails-6-and-earlier pre-history of the framework-absorbed feature. Together these establish Rails as the canonical ORM-layer-query-tag-propagation substrate on the wiki (patterns/query-comment-tag-propagation-via-orm). - —
Rails
.underscoreclass-name convention used to derive per-job-class Flipper flag names (InvoiceJob→disable_invoice_job). - — Rails test-suite parallelism + FactoryBot audit on CI.
- —
Rails substrate for PlanetScale's self-healing-Sidekiq
architecture: ActiveRecord
with_lock(row-levelSELECT FOR UPDATE),in_batchescursor iteration for bulk scheduler enqueue, ActiveJob'sset(wait:).perform_laterAPI composed intoperform_with_jitteronApplicationJob. The scheduler pattern and idempotent-job discipline sit on top of these Rails-framework primitives.
Related¶
- systems/sidekiq
- systems/flipper-gem
- systems/ruby-saml
- systems/activerecord-sql_commenter
- systems/marginalia-gem
- systems/fastpage-gem
- systems/mysql
- systems/innodb
- concepts/feature-flag
- concepts/factorybot-object-explosion
- concepts/rails-query-log-tags
- concepts/activerecord-annotate
- concepts/sqlcommenter-query-tagging
- concepts/offset-pagination-cost
- concepts/deferred-join
- concepts/cursor-pagination
- patterns/query-comment-tag-propagation-via-orm
- patterns/deferred-join-for-offset-pagination
- patterns/conditional-optimization-by-page-depth
Seen in — ActiveRecord query-rewriter gems¶
- — Mike Coutermarsh's 2022 introduction of PlanetScale's
fast_pagegem. Rails is the substrate for the ORM-level SQL-rewriter gem pattern: a method added toActiveRecord::Relationmechanically transforms a query chain into a more efficient equivalent — here, the deferred-join rewrite for deep-offset pagination. The post's canonical usage pattern is Rails-idiomatic method-chain composition:Post.all.order(created_at: :desc).limit(25).offset(100).fast_page. Cross-ecosystem companion: Hammerstone's Laravelfast-paginategem implements the same rewrite for Eloquent. Both gems confirm the broader observation that the ORM-query-rewriter pattern is ecosystem-portable — the rewrite is SQL-level, the gem is just the ergonomic wrapper.
Seen in — multi-database config + automatic role switching¶
-
— Taylor Barnett's PlanetScale Portals launch uses Rails' multiple-databases / automatic role switching as the canonical application-side integration for a read- write-split + regional read replica architecture. Three Rails-specific mechanisms are load-bearing in the post:
-
database.ymlmulti-connection —primary(write connection) +primary_replica(read connection withreplica: true). Rails treatsprimary_replicaas a read-only sibling ofprimaryfor monitoring / migration purposes. connected_to(role: :reading) do … end— explicit per-block routing for code that wants to force replica reads.ActiveRecord::Middleware::DatabaseSelectorwith{ delay: 2.seconds }— automatic role switching. Reads go toprimary_replicaby default; after any write, a session cookie pins the user's reads back toprimaryfor 2 seconds, preserving read-your-writes.
The Rails invocation is the canonical framework-level shape of the patterns/session-cookie-for-read-your-writes pattern — see that pattern page for the full recipe and equivalents in Django / Laravel / plain-driver apps. Code acknowledgment to Mike Coutermarsh (same PlanetScale-Rails engineer voice as the FastPage / SQLCommenter / self-healing- Sidekiq posts).
Seen in — application-generated public IDs via ActiveSupport concern¶
-
— Mike Coutermarsh (PlanetScale, 2022-03-29) discloses the full Rails
PublicIdGeneratorActiveSupport concern that generates 12-char base-36 NanoIDs as the externally-visiblepublic_idcolumn on every public-facing PlanetScale model. Rails-specific primitives that are load-bearing: -
ActiveSupport::Concern— the shared-module mechanism forinclude PublicIdGeneratorin models that need the pattern. Canonical Rails code-reuse idiom. before_create :set_public_id— ActiveRecord callback firing exactly once per row insert, before the INSERT SQL is issued so thepublic_idis populated at INSERT time (not UPDATE-later).self.class.where(public_id: public_id).exists?— pre-insert duplicate check for the bounded-retry correctness contract. (The real correctness primitive is the DB-sideUNIQUE KEY idx_public_id; the Rails check is a UX optimisation.)include PublicIdGeneratormodel declaration — the one-line activation of the concern per-model.
This is the canonical
public-id-alongside-BIGINT-PK pattern realised on Rails,
with full source code disclosure + matching Go publicid
package for cross-language consistency. Rails is the
substrate for the PublicIdGenerator concern + the schema
shape (id BIGINT AUTO_INCREMENT PRIMARY KEY + public_id
VARCHAR(12) UNIQUE KEY). Coutermarsh's first wiki ingest
as a PlanetScale author — earlier than his FastPage /
SQLCommenter / self-healing-Sidekiq / Portals work.
Seen in — ActiveRecord migrations + schema-change workflow¶
-
— Mike Coutermarsh (PlanetScale, 2023-03-20) canonicalises the Rails migration workflow on PlanetScale via the
planetscale_railsgem. Rails primitives that are load-bearing in the workflow: -
db/migrate/*.rb— ActiveRecord migration files withup/down/changemethods. Authored once, run against a PlanetScale dev branch viarake psdb:migrate, shipped to production through a deploy request. schema.rb— the canonical serialised schema snapshot. Updated bypsdb:migrateand committed alongside the migration file in the same PR.ActiveRecord::Base.ignored_columns— the bridge primitive for column drops. Addingself.ignored_columns += %w(category)tells ActiveRecord to behave as if the column doesn't exist, so the app ships ahead of the schema change. Canonical Rails idiom for code-before-schema drops per schema-change deploy order..find_each— batched iteration (default batch size 1,000) for memory-safe bulk data migrations. Load-bearing in the backfill template:Project.all.find_each { |p| p.update(:new_col, p.old_col) }— prevents the naiveProject.all.eachfrom materialising every row.- Rails console — production-shell entry point for data migrations (not schema migrations). Canonicalised as the correct altitude for data reshape after schema is in place.
- Multi-database support (Rails 6+) — composes with
the gem's
psdb:migrate:primary-style suffixes. - ActiveRecord callbacks — suggested as the
double-write mechanism during the five-step rename-
column recipe. The callback fires on
save/update, so the new column receives writes alongside the old one during the parallel-change window.
This is the Rails instantiation of PlanetScale's
branch-
based schema-change workflow. Parallels the earlier
Laravel post for PHP. The gem is the framework-specific
bridge that makes the platform's
deploy-request lifecycle feel
native to Rails engineers. Dogfooded on
app.planetscale.com before open-sourcing.