Deploying Rails applications shouldn't be complicated. While platforms like Heroku have been the go-to choice for many developers, Render has emerged as a compelling alternative that offers better performance, pricing, and developer experience for modern Rails applications.
Why Choose Render for Rails Deployment?
Advantages Over Other Platforms
Performance Benefits:
- Global CDN with edge caching
- Faster cold starts compared to Heroku
- Built-in SSL certificates
- HTTP/2 support out of the box
Developer Experience:
- Zero-configuration deployments
- Automatic deployments from Git
- Built-in database backups
- Real-time logs and monitoring
Cost Effectiveness:
- No sleeping dynos on paid plans
- More predictable pricing
- Free tier includes SSL and custom domains
Setting Up Your Rails App for Render
1. Preparing Your Application
First, ensure your Rails app is ready for production deployment:
# Gemfile
group :production do
gem 'pg' # PostgreSQL for production
end
group :development do
gem 'sqlite3' # SQLite for development
end
# Ensure you have these essential gems
gem 'puma' # Web server
gem 'bootsnap', require: false # Faster boot times
2. Database Configuration
Update your config/database.yml
:
production:
<<: *default
adapter: postgresql
url: <%= ENV['DATABASE_URL'] %>
pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
3. Environment Configuration
Configure config/environments/production.rb
:
Rails.application.configure do
config.cache_classes = true
config.eager_load = true
config.consider_all_requests_local = false
config.public_file_server.enabled = ENV['RAILS_SERVE_STATIC_FILES'].present?
# Asset configuration
config.assets.compile = false
config.assets.digest = true
# Security
config.force_ssl = true
config.ssl_options = { redirect: { exclude: -> request { request.path =~ /health/ } } }
# Logging
config.log_level = :info
config.log_tags = [ :request_id ]
end
Deployment Configuration
1. Create render.yaml
Create a render.yaml
file in your project root:
databases:
- name: myapp-db
databaseName: myapp_production
user: myapp_user
region: oregon
services:
- type: web
name: myapp-web
env: ruby
region: oregon
buildCommand: "./bin/render-build.sh"
startCommand: "bundle exec puma -C config/puma.rb"
healthCheckPath: /health
envVars:
- key: DATABASE_URL
fromDatabase:
name: myapp-db
property: connectionString
- key: RAILS_MASTER_KEY
sync: false
- key: RAILS_ENV
value: production
- key: WEB_CONCURRENCY
value: 2
2. Build Script
Create bin/render-build.sh
:
#!/usr/bin/env bash
# exit on error
set -o errexit
echo "Installing dependencies..."
bundle install
echo "Precompiling assets..."
bundle exec rails assets:precompile
echo "Cleaning old assets..."
bundle exec rails assets:clean
echo "Running database migrations..."
bundle exec rails db:migrate
echo "Build completed successfully!"
Make it executable:
bash
chmod +x bin/render-build.sh
3. Health Check Endpoint
Add a health check route for Render's monitoring:
# config/routes.rb
Rails.application.routes.draw do
get '/health', to: 'health#check'
# your other routes...
end
# app/controllers/health_controller.rb
class HealthController < ApplicationController
def check
render json: { status: 'ok', timestamp: Time.current }
end
end
Advanced Configuration
Environment Variables Management
Create a .env.example
file for team members:
# .env.example
DATABASE_URL=postgresql://username:password@localhost/myapp_development
RAILS_MASTER_KEY=your_master_key_here
REDIS_URL=redis://localhost:6379/0
SECRET_KEY_BASE=your_secret_key_base
Puma Configuration
Optimize config/puma.rb
for production:
# config/puma.rb
max_threads_count = ENV.fetch("RAILS_MAX_THREADS") { 5 }
min_threads_count = ENV.fetch("RAILS_MIN_THREADS") { max_threads_count }
threads min_threads_count, max_threads_count
worker_timeout 3600 if ENV.fetch("RAILS_ENV", "development") == "development"
port ENV.fetch("PORT") { 3000 }
environment ENV.fetch("RAILS_ENV") { "development" }
pidfile ENV.fetch("PIDFILE") { "tmp/pids/server.pid" }
workers ENV.fetch("WEB_CONCURRENCY") { 2 }
preload_app!
plugin :tmp_restart
before_fork do
ActiveRecord::Base.connection_pool.disconnect! if defined?(ActiveRecord)
end
on_worker_boot do
ActiveRecord::Base.establish_connection if defined?(ActiveRecord)
end
Deployment Process
1. Initial Setup on Render
- Connect your GitHub repository to Render
- Create a new Web Service
- Select your repository and branch
- Render will automatically detect your
render.yaml
- Set your environment variables in the Render dashboard
- Deploy!
2. Setting Environment Variables
In your Render dashboard, add these essential variables:
RAILS_MASTER_KEY
: Your Rails master keySECRET_KEY_BASE
: Generate withrails secret
- Any API keys or third-party service credentials
3. Database Setup
Render will automatically create and connect your PostgreSQL database based on your render.yaml
configuration.
Monitoring and Maintenance
Log Management
Access real-time logs through the Render dashboard or CLI:
# Install Render CLI
npm install -g @render/cli
# View logs
render logs -s your-service-name
Performance Monitoring
Monitor your application performance:
# Add to Gemfile for production monitoring
gem 'newrelic_rpm' # New Relic
# or
gem 'skylight' # Skylight
Automated Backups
Render automatically backs up your PostgreSQL database daily. Configure retention in your service settings.
Troubleshooting Common Issues
Build Failures
Asset Compilation Issues:
# In your build script, add more verbose output
RAILS_ENV=production bundle exec rails assets:precompile --trace
Database Connection Issues:
- Ensure DATABASE_URL
environment variable is set
- Check that your database service is running
- Verify connection in your database.yml
Performance Issues
Slow Response Times:
- Monitor database query performance
- Add database indexes for frequently queried columns
- Implement caching strategies
Memory Usage:
- Optimize your Puma worker and thread configuration
- Monitor memory usage in Render dashboard
- Consider upgrading your service plan
Best Practices
Security
- Always use environment variables for sensitive data
- Enable force SSL in production
- Keep dependencies updated
- Use strong secrets and rotate them regularly
Performance
- Implement HTTP caching headers
- Use a CDN for static assets
- Optimize database queries
- Monitor application performance metrics
Maintenance
- Set up automated database backups
- Monitor error rates and response times
- Keep Rails and gem versions updated
- Use staging environments for testing
Conclusion
Render provides an excellent platform for deploying Rails applications with minimal configuration and maximum performance. Its straightforward approach to deployment, combined with robust infrastructure and competitive pricing, makes it an ideal choice for both new projects and existing applications looking to migrate from other platforms.
The key to successful deployment is proper preparation: configure your application correctly, set up appropriate monitoring, and follow security best practices. With these foundations in place, Render will handle the heavy lifting of infrastructure management, allowing you to focus on building great features for your users.