BLUF (Bottom Line Up Front): Legacy CarrierWave implementations load entire files into memory during processing, causing severe memory spikes in background workers. The architectural fix is migrating to Shrine. Shrine’s modular architecture, powered by Shrine plugins, streams files directly and supports backgrounding natively, drastically reducing RAM usage.
| Aspect | CarrierWave | Shrine |
|---|---|---|
| Architecture | Monolithic uploader classes | Plugin-based, opt-in features |
| Background processing | carrierwave_backgrounder gem | Built-in backgrounding plugin |
| Direct uploads | carrierwave-aws + manual setup | shrine/plugins/presign_endpoint |
| Metadata extraction | Hard-coded in uploader | First-class via metadata plugins |
| Validation | Built-in but rigid | Composable via validation plugin |
| Test fixtures | File upload only | Mocked storage + in-memory storage |
| Rails coupling | Tightly coupled to Rails | Rails-agnostic core |
Phase 1: The Memory Problem
In older Rails applications, CarrierWave processes image thumbnails synchronously or requires brittle third-party gems for backgrounding.
Synthetic Engineering Context: CarrierWave Bloat
When a user uploads a 20MB image, CarrierWave reads it into RAM. If 10 users upload simultaneously, your worker process memory spikes, leading to an OOM (Out of Memory) crash.
# Legacy CarrierWave Uploader
class ImageUploader < CarrierWave::Uploader::Base
include CarrierWave::MiniMagick
# This block loads the file into memory synchronously
version :thumb do
process resize_to_fill: [200, 200]
end
end
Phase 2: The Shrine Solution
Shrine treats file uploads as streams and delegates features to isolated Shrine plugins. Direct uploads to S3 are handled client-side, and processing is offloaded cleanly.
# config/initializers/shrine.rb
require "shrine"
require "shrine/storage/s3"
Shrine.storages = {
cache: Shrine::Storage::S3.new(prefix: "cache", **s3_options),
store: Shrine::Storage::S3.new(prefix: "store", **s3_options),
}
# Enable crucial Shrine plugins
Shrine.plugin :activerecord # ActiveRecord integration
Shrine.plugin :cached_attachment_data # Retain cached file across form redisplays
Shrine.plugin :restore_cached_data # Extract metadata for cached files
Shrine.plugin :backgrounding # Asynchronous processing
By enabling the backgrounding plugin, Shrine promotes the cached file to permanent storage and generates thumbnails via Sidekiq, keeping the web process completely free of heavy I/O operations.
Need Help Stabilizing Your Legacy App? Replacing a core upload engine like CarrierWave requires careful data mapping and infrastructure changes. Our team at USEO can execute a CarrierWave to Shrine migration, optimizing your workers and eliminating OOM errors.