| name | rails-boot-profiling |
| description | Profile Rails application boot time to find slow requires. Use when the user asks why the app boots slowly, wants to profile boot time, or needs to optimize require/load performance. |
| gem | require-profiler |
| versions | >= 0.2 |
Rails Boot Time Profiling
Profile Rails application boot time using the require-profiler gem. This skill helps identify which require, load, YAML, and HTTP calls dominate startup time, and provides tools to drill deeper into slow files.
Prerequisites
Before profiling, ensure these conditions are met:
-
The require-profiler gem is in the Gemfile (at minimum in the development group).
-
Eager loading must be enabled for the environment you are profiling. Check the environment config:
config.eager_load = true
If eager_load is false, the profile will miss most application code — only files loaded during boot are captured, and lazy-loaded files will not appear.
- Add
-W0 to the Ruby command to suppress warnings and keep output clean.
Step 1: Run a Full Boot Profile
Run the base profiling command:
bundle exec ruby -W0 -r./config/boot -require-prof config/environment.rb
This loads config/boot.rb first (to set up Bundler and Bootsnap) and then profiles everything loaded by config/environment.rb.
The output is an indented tree showing each required file with its load time (self + children) in milliseconds:
config/environment.rb — 4312.071ms
config/application.rb — 3672.445ms
railties (>= 0) — 1023.112ms
actionpack (>= 0) — 412.331ms
actionview (>= 0) — 198.442ms
app/models/user.rb — 87.203ms
app/models/order.rb — 142.891ms
app/models/concerns/auditable.rb — 12.004ms
config/initializers/stripe.rb — 523.117ms
stripe (>= 0) — 498.201ms
To get a quick count of how many files were loaded:
bundle exec ruby -W0 -r./config/boot -require-prof config/environment.rb | wc -l
Step 2: Narrow the Scope
Filter by Threshold
Exclude files that loaded faster than a given number of milliseconds (supports floats):
REQUIRE_PROFILE_THRESHOLD=100 bundle exec ruby -W0 -r./config/boot -require-prof config/environment.rb
This shows only files that took 100ms or more to load — useful for quickly spotting the biggest offenders.
Filter by Focus Pattern
Show only files matching a pattern (uses Regexp.new(...) under the hood):
REQUIRE_PROFILE_FOCUS="stripe" bundle exec ruby -W0 -r./config/boot -require-prof config/environment.rb
The focus filter also keeps ancestor nodes in the tree, so you can see the full require chain leading to the matched files.
Combine both for a precise view:
REQUIRE_PROFILE_THRESHOLD=50 REQUIRE_PROFILE_FOCUS="initializers" bundle exec ruby -W0 -r./config/boot -require-prof config/environment.rb
Step 3: Check YAML and HTTP Activity During Boot
By default, require-profiler tracks YAML file loads (YAML.load_file, etc.) and adds them to the profile tree. This helps find initializers or gems that parse large YAML configs at boot time.
HTTP request tracking is also available but requires the sniffer gem to be in the Gemfile. This surfaces any HTTP calls made during boot (e.g., config fetches from remote services, gem activation pings).
To disable either:
REQUIRE_PROFILER_YAML=false bundle exec ruby -W0 -r./config/boot -require-prof config/environment.rb
REQUIRE_PROFILER_HTTP=false bundle exec ruby -W0 -r./config/boot -require-prof config/environment.rb
REQUIRE_PROFILER_PLUGINS=false bundle exec ruby -W0 -r./config/boot -require-prof config/environment.rb
Step 4: Deep-Dive with Stackprof
When you identify a file that is unexpectedly slow to load, use Stackprof to profile what happens inside that file during require:
REQUIRE_PROFILE_STACKPROF=config/initializers/stripe.rb bundle exec ruby -W0 -r./config/boot -require-prof config/environment.rb
The stackprof gem must be in the Gemfile. This generates two files:
config-initializers-stripe-stackprof.json — JSON format, viewable in Speedscope
config-initializers-stripe-stackprof.dump — raw Stackprof data, analyzable with the stackprof CLI
To analyze with the stackprof CLI:
bundle exec stackprof config-initializers-stripe-stackprof.dump
bundle exec stackprof config-initializers-stripe-stackprof.dump --method 'ClassName#method_name'
To view in Speedscope, open https://www.speedscope.app/ and drag the .json file onto the page (nothing is uploaded — parsing is local).
Step 5: Export as JSON for Speedscope
Generate a Speedscope-compatible JSON profile of the entire boot:
REQUIRE_PROFILE_PATH=tmp/require-profile.json bundle exec ruby -W0 -r./config/boot -require-prof config/environment.rb
This writes a JSON file conforming to the Speedscope file format schema. Open it in Speedscope and use the Left Heavy view to find the most expensive require chains, and the Sandwich view to find files that appear repeatedly across different chains.
If the Speedscope CLI is installed (npm install -g speedscope), open it directly:
npx speedscope tmp/require-profile.json
You can also use the REQUIRE_PROFILE_FORMAT env var to select the output format explicitly (text, json, or call_stack). When the output path ends in .json, the JSON format is selected automatically.
Collapsed Call Stack Format
For flame graph generation with external tools (e.g., flamegraph.pl, inferno), use the collapsed call stack format:
REQUIRE_PROFILE_FORMAT=call_stack REQUIRE_PROFILE_PATH=tmp/require-profile.txt bundle exec ruby -W0 -r./config/boot -require-prof config/environment.rb
This emits one line per stack in Brendan Gregg's collapsed format with per-frame self time in milliseconds.
Environment Variable Reference
| Variable | Purpose | Example |
|---|
REQUIRE_PROFILE_THRESHOLD | Minimum load time in ms to include (float) | 100, 50.5 |
REQUIRE_PROFILE_FOCUS | Regexp pattern to filter files | "stripe", "initializers" |
REQUIRE_PROFILE_PATH | Output file path (enables file output) | tmp/require-profile.json |
REQUIRE_PROFILE_FORMAT | Output format: text, json, call_stack | json |
REQUIRE_PROFILE_STACKPROF | File path to deep-profile with Stackprof | config/initializers/stripe.rb |
REQUIRE_PROFILER_YAML | Disable YAML tracking when set to false | false |
REQUIRE_PROFILER_HTTP | Disable HTTP tracking when set to false | false |
REQUIRE_PROFILER_PLUGINS | Disable all plugins when set to false | false |
Important: Use the Profiler's Built-in Filtering
Prefer profiler's built-in filtering and searching capabilities over grep, tail, head, awk, or sed to filter or search results.:
- To find slow files → use
REQUIRE_PROFILE_THRESHOLD, not grep for timing patterns
- To investigate a specific gem or file → use
REQUIRE_PROFILE_FOCUS, not grep for the name
- To reduce output size → use
REQUIRE_PROFILE_THRESHOLD + REQUIRE_PROFILE_FOCUS, not tail -N | head -M
Shell-based filtering breaks the indented tree structure (you lose parent-child relationships), misses context, and requires re-running the full profile each time you change the filter. The built-in env vars preserve the tree, show ancestor chains, and handle edge cases the profiler already knows about.
The only acceptable uses of piping are:
| wc -l to count total loaded files in step 1
- Piping into a file when
REQUIRE_PROFILE_PATH is not available
Recommended Agent Workflow
Follow this sequence when a user asks about slow boot time:
-
Get a baseline. Run the full profile command and note the total boot time (the top-level entry's duration) and total file count (| wc -l).
bundle exec ruby -W0 -r./config/boot -require-prof config/environment.rb
-
Find the top offenders. Re-run with REQUIRE_PROFILE_THRESHOLD to surface only slow files. Start with a threshold that shows roughly 10-20 entries (e.g., if total boot is ~4s, try 100ms; if ~1s, try 30ms). Report the top slowest entries to the user.
REQUIRE_PROFILE_THRESHOLD=100 bundle exec ruby -W0 -r./config/boot -require-prof config/environment.rb
-
Investigate specific areas. Use REQUIRE_PROFILE_FOCUS to zoom into a gem, initializer, or file. The focus pattern is a regexp — use it to match file paths, gem names, or directory patterns. Combine with REQUIRE_PROFILE_THRESHOLD for precision.
REQUIRE_PROFILE_FOCUS="stripe" bundle exec ruby -W0 -r./config/boot -require-prof config/environment.rb
REQUIRE_PROFILE_THRESHOLD=50 REQUIRE_PROFILE_FOCUS="initializers" bundle exec ruby -W0 -r./config/boot -require-prof config/environment.rb
-
Check for boot-time side effects. YAML and HTTP entries appear in the profile tree by default. HTTP calls during boot are almost always worth investigating — they add latency and can fail. Use REQUIRE_PROFILE_FOCUS to find them:
REQUIRE_PROFILE_FOCUS="\.yml" bundle exec ruby -W0 -r./config/boot -require-prof config/environment.rb
REQUIRE_PROFILE_FOCUS="(GET|POST|PATCH|DELETE):" bundle exec ruby -W0 -r./config/boot -require-prof config/environment.rb
-
Deep-dive when needed. For files that are unexpectedly slow (the load time seems too high for what the file does), use REQUIRE_PROFILE_STACKPROF to generate a Stackprof profile and identify what's happening inside that file.