The Boundary ActiveAdmin Forces: HTML Admin vs API Controllers
ActiveAdmin needs a full Rails web boundary, while API-only endpoints need a lean controller. Compare the two paths to see where sessions, assets, and browser protections belong.
Loading…
Topic
36 posts about Ruby on Rails. Every summary links to the original.
See the idea
ActiveAdmin needs a full Rails web boundary, while API-only endpoints need a lean controller. Compare the two paths to see where sessions, assets, and browser protections belong.
The Good Stuff
Paid picks we use ourselves. Links carry a referral code — a subscription through one earns us a commission at no extra cost to you.
Newest first
Intercom’s outage began with a page about elevated exceptions, leading engineers to dive into Datadog and uncover a lurking 32-bit integer limit in one of the most critical parts of the app’s data model. The chaotic five-hour incident marathon required monkey patches, data migrations, and feature flag gymnastics to restore normal operations. After stabilizing the system, the team applied important technical changes to the Rails application to prevent integer overflow and similar failures. Miles McGuire presented the postmortem at Rails World 2024, sharing the debugging process and the key lessons learned from the unusual incident. The talk covers monitoring data model limits, using feature flags for safe rollouts, and enhancing application resilience to avoid future recurrence.
Shared-nothing architecture is presented as a scaling model for Showcase, a Ruby on Rails ballroom-competition application that began on a Mac Mini and grew to cloud VMs serving events in multiple regions. Because each event has few geographically concentrated users, a roughly one-megabyte SQLite database, about one transaction per second, and typical response times of 100ms or less, the design keeps state separate rather than sharing databases and Redis across events. The implementation runs an event’s services on one Fly.io VM, repeats that unit across machines or regions, and can place multiple event instances on one server with Phusion Passenger, NGINX, volumes, and a shared Action Cable process. It specifies 1GB machines with 2G swap after observing about 220MB idle and 450MB active RAM, and recommends WireGuard; the conclusion is that local state and fewer network calls suit this workload and can improve throughput and reliability.
Resend introduces Mateus Resende as a Software Engineer based in Belo Horizonte, Brazil. He began working in software in 2015, first as a Ruby and Ruby on Rails developer before moving across domains including e-commerce recommendations, vehicle tracking, fintech, and email systems. A snowstorm during his exchange at SUNY Buffalo led him to discover MIT OpenCourseWare, code for hours, and later switch from Electrical Engineering to Computer Science. At Resend, he says its remote and async culture, extensive documentation, and developer-oriented product and company shaped his decision to join. His approach to engineering emphasizes balancing quality with speed and tailoring solutions to users and reviewers, while he recommends fundamentals such as testing, Domain-Driven Design, and Evolutionary Architectures over relying on hyped LLM coding techniques.
Intercom describes how it averages 180 production ships per workday in January 2026 while targeting 99.8+% availability, with an average 12-minute merge-to-production cycle. The post focuses on its Ruby on Rails monolith, deployed to three data-hosting regions through independent pipelines, and frames small batches as a way to limit accumulated risk. An automated pipeline builds a deployable slug, runs parallel CI, verifies it in pre-production with boot, CI, and Datadog Synthetics gates, then performs a staggered rollout with process-level rolling restarts. Safety also depends on engineer ownership, feature flags, production testing on a single host, outcome-focused heartbeat metrics, and rapid automatic or manual rollbacks. Incident reviews then harden the system, supporting the conclusion that speed is used to keep changes small, feedback immediate, and recovery fast rather than to trade stability for velocity.
Heroku’s Router 2.0 beta exposed elevated tail response times and request failures in a subset of Puma applications, especially under 200 milliseconds of server-side lag and 30 requests per second. Investigation compared legacy and Router 2.0 connections, examined TIME_WAIT behavior, and tested Go’s http.Transport idle-connection limit; raising MaxIdleConnsPerHost from the default of 2 to 100 stabilized connection states but did not improve latency. The underlying issue was Puma’s handling of persistent connections, where request balancing could leave work queued behind busy connections; disabling keepalives eliminated the problem, while thread, worker, and max_fast_inline tuning were offered as alternatives. Load tests found the issue unique to Puma, and the update reports that Puma 7.0 fixed the bug, recommending version 7.0.4 or higher.
Globally distributed Postgres describes a way to serve a conventional CRUD application across regions while keeping Postgres writes directed to one primary and reads near users. Fly’s proxy sends each request to the local application instance, where most requests succeed; when a write reaches a read-only replica, Rails catches PG::ReadOnlySqlTransaction and returns a fly-replay header naming PRIMARY_REGION. The proxy then retries the complete HTTP request inside its network, avoiding per-query cross-region database routing and allowing the application to retain its ordinary connection behavior. The approach can also support session-based read-your-own-writes and replica-freshness checks, but it is not suitable for every workload; the text contrasts it with geographically distributed databases such as CockroachDB.
The post presents object-allocation profiling as a way to find Ruby performance hotspots, including code inside libraries such as Active Record. It uses memory_profiler and derailed_benchmarks to group allocations by gem, file, and source location, then examines whether each allocation can be removed or avoided. A benchmark compares a direct maximum comparison with an array-based version: the array allocation makes the latter 2.04x slower in the reported run. One optimization for cache_version reuses a raw database timestamp string when it is safe, checking its type, format, timezone, and provenance before deleting separators and padding PostgreSQL-truncated values. This change reduces allocation from 743,842 bytes and 6,626 objects to 702,955 bytes and 6,063 objects, and the post reports up to 1.12x faster; combined optimizations reach 1.23x overall.
Dev Degree is Shopify’s work-integrated learning program, designed to combine an accredited computer science degree with four years of continuous developer experience. Students take three university courses per semester while working 25 hours weekly, beginning with Shopify-led skills training before moving through four team placements across disciplines such as back-end, front-end, data, security, and production engineering. The program teaches tools and technologies including Git and GitHub, Ruby, Rails, React, TypeScript, and GraphQL, while emphasizing mentorship, feedback, personal development, and support from a multidisciplinary team working with university partners. The first cohort graduated on April 24, 2020, after adapting to program changes and remote learning during the pandemic; the post reports that 100% of graduates accepted full-time positions within six months.
Performance regressions can accumulate in a large monolithic Rails application, making it difficult to identify offending changes among thousands of daily commits. The post presents profiling and benchmarking as complementary practices: profiling locates runtime bottlenecks, while benchmarking compares code paths and validates fixes. It covers elapsed time, CPU versus wall time, object allocations, TracePoint and ObjectSpace, plus rbspy, stackprof, rack-mini-profiler, and App Profiler, which supports on-demand remote production profiling at Shopify. A flamegraph example showed garbage collection consuming about 35% of CPU time in a slow request, and the team inferred excessive Ruby object allocation; a Rails benchmark showed roughly 50x improvement from caching an order’s total price calculation. The discussion cautions against micro-optimizations whose gains do not justify code changes and recommends addressing larger performance issues first.
Shopify’s Ruby on Rails Shop model had grown beyond 3,000 lines, accumulated numerous responsibilities, and developed weak semantic boundaries, making store settings a target for extraction. The team used Flog’s ABC-based score—assignments, branches, and calls—to identify a particularly disordered area, then applied Martin Fowler’s Strangler Fig Pattern to move the locked_settings behavior into Capital::SettingsToLock and a dedicated record/data source. The seven-step process defined and tested a new interface, redirected callers, introduced and backfilled the new data source, switched reads, and finally stopped legacy writes and removed the old column and code. Keeping the old system available during the transition supported incremental changes, monitoring, reversibility, and the stated no-downtime requirement; the completed example left the new system in place with legacy remnants removed.
Misconfigured circuit breakers can leave an application effectively unavailable during a dependency outage by allowing timed-out requests to consume worker capacity. Using Shopify’s Semian implementation, the post explains how name, error_threshold, error_timeout, half_open_resource_timeout, and success_threshold govern circuit opening, recovery, and wasted utilization across failing service instances. It models timeout spikes for a single worker, notes that separate names isolate services and instances, and presents an equation for steady-state additional utilization, while noting that context-switch costs are not included. A live test closely matched the equation’s prediction. In a Rails worker with two threads and 42 Redis instances, changing half_open_resource_timeout from 0.25 seconds to 50ms and error_timeout from 2 to 30 seconds reduced modeled extra utilization from 263% to 4%, with slower recovery; an author’s edit says success_threshold does not affect steady-state utilization.
Shopify built Identity to reduce the overhead of managing separate staff accounts across multiple stores, where each Shop isolated user data and lacked single sign-on. The service uses OpenID Connect (OIDC) to centralize authentication while retaining destination-specific authorization, and it models legacy one-store accounts separately from Identity accounts that can access multiple destinations. Migration begins by synchronizing profile and security data, routing authentication through Identity, and prompting eligible users to verify email ownership, combine accounts, and provide required 2FA credentials. Single legacy accounts can be auto-upgraded without changing their UUID, while multi-account merges use a MergeSession and operations implemented with ActiveOperation; WebAuthn also supports physical security keys as a second factor. Finally, Shopify changed store signup and staff invitations to prevent new legacy accounts, reporting that more than 75% of active accounts had been upgraded or combined at the time of writing.
Sam Saffron discusses Discourse’s approach to Ruby performance and monitoring, arguing that production memory constraints matter more than isolated microbenchmarks for many deployments. He favors clear code and selective optimization, sometimes bypassing ActiveRecord with MiniSql on performance-sensitive paths rather than broadly sacrificing Ruby’s readability. Discourse keeps performance under continuous observation, and Saffron describes budgets for dependencies, boot time, and high-profile pages, including alerts for query-count regressions. He identifies memory leaks as especially difficult to diagnose, describes bisecting an application to isolate a V8-Ruby interop leak, and says MRI remains the only feasible runtime for Discourse while memory profiling and analysis tooling remain substantially behind Java and .NET.
Shopify’s guide presents performance advice for Ruby on Rails across Active Record, Rails, and Ruby, while treating speed as a feature rather than the first optimization priority. It recommends understanding Active Record’s lazy query execution, selecting fewer columns, avoiding unindexed queries, using safe indexing approaches for large tables, and treating query cache as short-lived rather than dependable. For Rails applications, it covers caching, throttling expensive or abusive operations, moving long-running work into Active Job-backed queues, and reducing dependency growth to limit boot time and memory use. Ruby-specific guidance includes limiting metaprogramming and indirection, choosing O(1) hash lookups over O(n) array searches when appropriate, and reducing allocations while avoiding harmful global mutation; benchmark figures show method-definition and invocation costs can differ.
Shopify describes running its Core monolith on the unreleased Rails 6 master branch, or “Edge of Rails,” since February 2019, with the goal of continuously using the framework’s latest revision. Instead of annual upgrades, weekly changes reduce diff size and let developers use upstream features quickly, while a 130,000-plus-test suite finds edge cases and informs patches to Rails and related projects such as Zeitwerk. Solid Track automates weekly Rails bumps, opens GitHub pull requests, and triggers git bisect when CI fails to identify the breaking commit. Green builds move through ten-minute canary deployments before reaching the remaining servers. The approach trades the stability of released dependencies for faster fixes and features, relying on monitoring, tests, and controlled deployment to manage risk.
Shopify's application security program is designed to preserve safety while products and services scale quickly across a platform serving more than 800,000 merchants. It organizes the work around scaling secure applications, scaling security teams, and scaling security interactions, with a culture that treats security as a non-negotiable priority. Standardizing on Ruby on Rails and other shared technologies lets tooling go deep, while service tracking provides visibility into applications, dependencies, code, and automated dependency updates. The security organization grew from one employee into specialized teams, supplemented by penetration testing, bug bounties, and audits, while incident response remains shared across the company. At the code level, tripwires detect dangerous patterns early; Shopify renamed html_safe to dangerously_output_as_html, links flagged pull requests to XSS training, and alerts Application Security, shifting review toward automation.
Production database performance in Rails can degrade as application and data volumes grow, with slow queries, unnecessary queries, and other database bottlenecks becoming significant constraints. The post recommends establishing monitoring early, using Heroku Postgres events, data.heroku.com diagnostics, and the pg-extras pg:outliers command to locate expensive queries, then checking Rails access patterns such as unnecessary association loads. It shows how ActiveRecord includes can reduce a collection example from 11 queries to two, and explains when indexes may help, including Rails migrations for indexed columns and foreign keys, while noting storage and write costs. It also presents fragment caching with Redis as a further optimization and points to connection leaks, locks, and VACUUM as additional areas to investigate, urging benchmarking and metrics for every change.
Kirsten Westeinde’s just-over-five-year Shopify career spans internal tools, partner-facing applications, and backend development on Kit as the company scaled. She began with Ruby on Rails, later helped extract partner software from Shopify Core using Elasticsearch, Kafka, Ruby on Rails, and the Shopify API, and now works with Data Engineering on real-time recommendations. The feature combines Go and Ruby and is designed to handle the current load while scaling to future demand. Her problem-solving practices include whiteboarding system interactions, taking mental breaks, and writing or explaining ideas to align collaborators. She also describes mentorship, pair programming, a women’s developer meetup, and f(empower) as ways to support growth and address exclusion, bias, and microaggressions in technology.
Shopify describes why its decade-old Ruby on Rails monolith became difficult to change as the codebase and development organization grew. High coupling and absent boundaries made innocuous changes trigger unrelated test failures, slowed CI, and forced developers to absorb excessive domain context, while microservices would add deployment, infrastructure, network, and coordination costs. The chosen path was a modular monolith: retain one codebase and deployment unit while separating domains through strictly enforced component boundaries. Shopify’s Componentization effort was informed by a developer survey and uses Wedge to score components and report violations, including cross-component associations and calls that bypass explicitly public interfaces. Boundary enforcement at runtime remains a future goal, but dependency isolation has already enabled replacing a legacy tax engine with a new tax calculation system.
Canada’s 2018 cannabis legalization required Shopify to support a new, tightly regulated retail industry while keeping personal information in Canada. Using Google Cloud Platform’s Montreal region, the team created a Canadian Shopify instance with Terraform-managed projects, regional clusters, segregated workloads, PCI-compliant payment infrastructure, and a regional data warehouse. Because consumer behavior and peak demand were uncertain, engineers modeled traffic scenarios, ran repeated load tests across storefront actions, tested bot attacks, held pre-mortems, and provisioned five times projected launch traffic and sales. Multiple safeguards—including application-level endpoint checks, firewalls, limited secrets, unique SSL certificates, monitoring, and alerting—were layered to prevent data from crossing jurisdictions. Merchants opened across time zones, and the first legal sale occurred on Shopify’s point of sale in Newfoundland at 12:01 NST, followed by launches with zero downtime, excellent performance, and secure Canadian data storage and transmission.
The best engineering reads, once a week.