Performance

Solving Rails Asset Pipeline Memory Bloat

BLUF (Bottom Line Up Front): The rake assets:precompile task in legacy Rails applications often crashes due to memory bloat, especially in CI/CD environments. This happens because the Ruby process and the Node.js process (Webpack) run simultaneously, exhausting container limits. The fix involves setting Node.js heap limits and isolating the build processes.

Phase 1: The CI/CD Crash

Glossary entry: Asset Pipeline Memory Spikes.

Legacy apps utilizing both Sprockets and Webpacker are extremely heavy to build. Sprockets loads the entire Rails environment, while Webpacker boots a V8 JavaScript engine.

Synthetic Engineering Context: OOM Error

During a GitLab CI or GitHub Actions run, the build fails abruptly without a clear Ruby stack trace.

# CI/CD Log Output
$ RAILS_ENV=production bundle exec rake assets:precompile
Compiling...
Killed
make: *** [Makefile:12: build] Error 137

Exit code 137 strictly means the container was killed by the OS for exceeding its memory limit (usually 2GB or 4GB on standard CI runners).

Phase 2: Restricting Memory Usage

To prevent the Rake task memory from exceeding bounds, we must constrain the Node.js heap and prevent Sprockets from retaining unneeded objects.

Execution: Node.js Heap Limit

By default, Node.js can consume up to 1.5GB of RAM. You must restrict this via the NODE_OPTIONS environment variable.

# Set max old space size to 1024MB (1GB)
export NODE_OPTIONS="--max_old_space_size=1024"
RAILS_ENV=production bundle exec rake assets:precompile

Execution: Disabling Source Maps

In legacy Webpacker, generating source maps for production doubles the memory requirement. Disable them in config/webpacker.yml.

# config/webpacker.yml
production:
  <<: *default
  compile: false
  extract_css: true
  cache_manifest: true
  # Disable source maps to save memory during precompilation
  source_map: false 

If memory is still an issue, you can configure your CI to add temporary swap space before running the precompile task.

Phase 3: Next Steps & Risk Mitigation

Tweaking heap limits is a temporary patch. The long-term architectural solution is completely removing Webpack and Node.js from the Rails pipeline by migrating to jsbundling-rails (esbuild) or importmap-rails.

Need Help Stabilizing Your Legacy App? Failing CI pipelines kill engineering velocity. Our team at USEO modernizes legacy asset pipelines, dropping build times from minutes to seconds.

Contact us for a Technical Debt Audit