Active Storage was initially built by 37Signals for Basecamp, their project management app. Since users in a company were not supposed to view files of other users in another company, and many of these files were sensitive, they built Active Storage to generate temporary links when the page containing those files was opened. This was done through “redirect mode”.
This mode can be used for images, as long as you are only using them in your own website, and not using fragment caching in the views that contain those URLs. If you need to send them through an email, slack message, or anything similar, redirect mode won’t work since the link will expire after 5 minutes. Redirect mode also does not work with CDN caching, since the URL is not a file, but another URL.
In Rails 6 this was changed with proxy mode, where Rails streams the file from storage. This keeps the main advantage of Active Storage, which is on-the-fly image transformations (compress, crop, resize, etc), but increases load on the servers since you have puma workers stuck streaming the data. This is the one I use, but I keep nginx in front of Puma, with object caching and buffering enabled, so each file is served only once, which solves the extra load problem.
Finally, public mode was added to avoid the whole “urls expires” and “files need streaming”. The problem of this mode, is that if you need a image variant, you need to process it before generating the url to put in the HTML. So if you have a feature where a user uploads multiple images (let’s say 5), and in the next page you show thumbnails of these images, your users will spend a long time looking at a blank page while active storage processes those 5 images to generate the urls.
TL:DR:
- Use redirect mode if you images are only visible in your web app (no emails, no slack/whatsapp/discord, etc)
- Use proxy mode if you have a proxy type CDN (Cloudflare) so they can be cached.
- Use public mode if you need images to be visible outside your app.
You can actually use all three modes at the same time. In your case, the simplest would be stay in redirect mode, and when necessary, use the public url of the image.
So in your views:
<%= image_tag user.avatar.variant(resize: [100,0] %>
And in your emails:
<%= image_tag user.avatar.variant(resize: [100, 0]).processed.url
Just make sure your storage.yml
file has public: true
in the config for S3/R2/etc.