Hey friends, I’m running into a serious issue every time I deploy my rails app on render and am losing customers because of it! Specifically I think there’s an edge case with the distribution of the precompiled assets which breaks the app until the user resets their browser cache:
- Render finishing deploy, and the new version & old version are running in parallel for some short amount of time
- User access app, pointing them to the new asset (or old asset) (I’ve intermittently reproduced this issue with both .js & .css files)
- For some reason my app returns a 404 for the requested asset, which is cached by the user’s browser.
- User keeps refreshing the app but since it is cached it’s stuck in a bad state, leaving the app in a broken state unless user clean the browser cache
I love Render a lot but my customers are really bothered by this. So I need to move to another provider if I don’t manage to fix it soon… But maybe I’m doing something wrong on my end? Here’s the configurations of my app. Turning config.public_file_server.enabled
on helped a lot but did not completely resolve the issue.
config/environments/production.rb
Rails.application.configure do
#...
config.enable_reloading = false
config.eager_load = true
config.consider_all_requests_local = false
config.action_controller.perform_caching = true
config.require_master_key = true
# Turning this on for render environment in attempt to fix the deploy-time css crash issue, but doesn't seem to help
# Taken from https://community.render.com/t/rails-static-assets-behaviors/3360
config.public_file_server.enabled = ENV["RAILS_SERVE_STATIC_FILES"].present? || ENV["RENDER"].present?
config.assets.compile = false
config.force_ssl = true
end
applicaiton.html.erb
<!DOCTYPE html>
<html>
<head>
<%= csrf_meta_tags %>
<%= csp_meta_tag %>
<%= stylesheet_link_tag "application", media: "all", "data-turbo-track": "reload" %>
<%= javascript_include_tag "application", "data-turbo-track": "reload", defer: true %>
</head>
<body>
<!-- ... -->
</body>
</html>
render.yaml
services:
- type: redis
name: xxx-redis
region: ohio
maxmemoryPolicy: noeviction
ipAllowList: [] # only allow internal connections
plan: starter
- type: web
name: xxx-web
repo: https://github.com/xxx
runtime: ruby
region: ohio
healthCheckPath: /up
buildCommand: "./bin/render-build.sh"
preDeployCommand: "bundle exec rails db:migrate"
startCommand: bundle exec rails s -e production
envVars:
- key: DATABASE_URL
fromDatabase:
name: xxx-postgres
property: connectionString
- key: REDIS_URL
fromService:
type: redis
name: xxx-redis
property: connectionString
- key: RAILS_MASTER_KEY
sync: false
- key: MALLOC_ARENA_MAX
value: 2 # renduce memory usage, https://www.mikeperham.com/2018/04/25/taming-rails-memory-bloat/
- key: WEB_CONCURRENCY
value: 2
plan: standard
- type: worker
name: xxx-worker
runtime: ruby
region: ohio
buildCommand: "./bin/render-build.sh"
startCommand: bundle exec sidekiq -e production
envVars:
- key: DATABASE_URL
fromDatabase:
name: xxx-postgres
property: connectionString
- key: REDIS_URL
fromService:
type: redis
name: xxx-redis
property: connectionString
- key: RAILS_MASTER_KEY
sync: false
- key: MALLOC_ARENA_MAX
value: 2 # renduce memory usage, https://www.mikeperham.com/2018/04/25/taming-rails-memory-bloat/
plan: starter
./bin/render-build.sh
#!/usr/bin/env bash
# exit on error
set -o errexit
bundle install
bundle exec rake assets:precompile
bundle exec rake assets:clean