Deploy Rails and Memcache on Render: A How-To Guide
Do you want to deploy a Ruby on Rails application on Render and boost its performance with Memcache? In this tutorial, you’ll create a simple Rails contact list app, deploy it to Render, and finally use Memcache to speed it up.
Memcache serves as an in-memory data storage system, a tool that significantly enhances the efficiency and scalability of web applications. Consider integrating Memcache if your pages exhibit sluggish load times or your application faces scaling challenges. Regardless of your app’s size, Memcache has the potential to quicken page loads and help future-proof your app.
Outline
- Initialize a Rails project
- Create a Rails contact list app
- Configure your app for Render
- Deploy Rails to Render
- Set up caching in Rails
- Implement caching strategies in Rails
Prerequisites
- Familiarity with Ruby and Rails.
- A Render account.
- A GitHub account and Git installed on your local machine. To deploy to Render, you must push code to a remote code repository. Render supports GitHub and GitLab.
- Ruby version
>=2.7.0
installed on your computer.2.7.0
is the minimum Ruby version required by Rails 7.
Initialize a Rails project
To begin, install Rails on your computer by running the following command in your terminal:
gem install rails
This tutorial uses Rails version 7.0.5
, but the steps should be compatible with 5and 6
. You can your installed version by running the following command in your terminal:
rails --version
If you see the message Rails is not currently installed on this system...
after installing Rails, the terminal window likely doesn’t know about the path to the rails
executable that was just added. Try opening a new terminal window and re-run the command.
Run the following command to create a new project with the rails
CLI:
rails new rails_memcache
The argument after the new
command is your application name. For this tutorial, I’ll use rails_memcache
.
Change into your newly created project directory:
cd rails_memcache
Run the Rails web server, Puma:
rails server
Visit http://127.0.0.1:3000/ in your browser to see your basic Rails app running.
Create a Rails contact list app
Use the Rails scaffold generator to create an interface for storing and viewing a simple directory of names and email addresses. In your terminal, run the following:
rails g scaffold contact name:string email:string
The g
in this command stands for generate
. The scaffold
generator creates a new model, database migration for that model, controller to manipulate it, and views to view and manage the data. contact
is the name of the model being generated. name
and email
are the fields, of type string
, to be added to the contact
model.
Next, run the migration you just created:
rails db:migrate
Open config/routes.rb
in your code editor and set contacts#index
as the root
path route:
# config/routes.rb
Rails.application.routes.draw do
# ...
:to => 'contacts#index'
root end
Note # ...
denotes code removed for brevity.
Your simple contact list app is now functional. With Rails’ server running, rails server
, Visit http://127.0.0.1:3000/ in your browser and try it out. You should be able to add and delete contacts, to view all contacts, and to view a single contact.
Configure your app for Render
To prepare your Rails app to be deployed to Render, you’ll do the following:
- Add Render’s platform to your
Gemfile.lock
- Configure Rails to use PostgreSQL
- Create a Render build script
- Define your Render infrastructure as code
- Create a remote code repository for your app
Add Render’s platform to your Gemfile.lock
Render ruby
web service runtime uses the x86_64-linux
platform. Add it to your Gemfile.lock
to help to avoid issues where a gem works on one platform but not on another. For example, if you develop on a macOS machine. In your terminal, run the following command:
bundle lock --add-platform x86_64-linux
Configure Rails to use PostgreSQL in production
Your Rails app is configured to use SQLite by default. You’ll update the database configuration to use SQLite in development and PostgreSQL in production.
Open up Gemfile
in your code editor. Find the following line:
# Gemfile
#...
"sqlite3", "<version>"
gem #...
And replace it with the following:
# Gemfile
# ...
:development do
group 'sqlite3'
gem end
:production do
group 'pg'
gem end
# ...
This configuration ensures the sqlite3
gem is used in development and the pg
gem in production.
To avoid locally installing gems in the production group in your Gemfile
, run the following command in your terminal:
bundle config set --local without 'production'
That command will create a local bundle config file .bundle/config
, which is excluded in .gitignore
.
To update your Gemfile.lock
file, run the following:
bundle install
Next, open config/database.yml
in your code editor. Update the production
database configuration to use a connection string with the DATABASE_URL
environment variable:
# config/database.yml
# ...
production:
<<: *default
url: <%= ENV['DATABASE_URL'] %>
Note you are replacing the line database: db/production.sqlite3
.
The DATABASE_URL
environment variable will be your Render PostgreSQL database internal URL. You will set the variable in your app’s Web Service environment when you provision your Render infrastructure in the step Define your Render infrastructure as code.
Create a Render build script
You’ll next create a build script for Render to install Rails dependencies and run database migrations. Create a file bin/render-build.sh
in your project root directory and add the following:
#!/usr/bin/env bash
# exit on error
set -o errexit
bundle install
bundle exec rails assets:precompile
bundle exec rails assets:clean
bundle exec rails db:migrate
rails assets:precompile
takes your assets (JavaScript, CSS, images, etc.), processes them, minimizes them (when applicable), and then puts the results into the public/assets
directory.
rails assets:clean
removes old, compiled assets from the public/assets
directory. This is useful because the assets:precompile
task generates fingerprinted versions of your assets, and over time, as you make changes to your assets and recompile them, old and unused assets can accumulate and take up space.
The bundle exec
part is just a way to ensure that the command is run in the context of your current bundle (the specific set of gems specified in your Gemfile
).
Make the script executable:
chmod a+x bin/render-build.sh
The chmod
command changes the file’s permissions, and a+x
means “add execute permission for all users”.
In the next step, you’ll configure Render to run this script on every git push
.
Define your Render infrastructure as code
Create a render.yaml
Blueprint spec file in your project root directory. You’ll define a Rails Web Service and PostgreSQL Database in the spec.
# render.yaml
databases:
- name: rails_memcache
plan: free
databaseName: rails_memcache
user: rails_memcache
services:
- type: web
plan: free
name: rails_memcache
runtime: ruby
buildCommand: "./bin/render-build.sh"
startCommand: "bundle exec puma -C config/puma.rb"
envVars:
- key: DATABASE_URL
fromDatabase:
name: rails_memcache
property: connectionString
- key: RAILS_MASTER_KEY
sync: false
Note you’re specifying Render’s Free plan, which is sufficient for this tutorial. The default plan is Starter.
The buildCommand
property runs the bin/render-build.sh
script you created in the previous step.
RAILS_MASTER_KEY
has the property sync: false
, making it a Render placeholder environment variable. Placeholder environment variables are those which you want to exclude from your Blueprint spec and are not generated, such as external secrets. You will later be prompted to enter your RAILS_MASTER_KEY
value on the Render dashboard before your deployment is finalized.
See the Render Blueprint spec documentation for an explanation of all properties.
Create a remote code repository for your app
To deploy to Render, you need a remote code repository. In this step, you’ll commit your code to your app’s git repository and push it to GitHub.
Apps generated with the rails new
CLI command come with an initialized git repo and a .gitignore
file. So you can stage your code:
git add .
And commit:
git commit -m 'Initial commit: Create contacts app'
Now your code is committed, you’ll push it to GitHub.
In your browser, log in to GitHub and create an empty repository called rails_memcache. The repo can be public or private.
Back in the terminal, add your GitHub repo as a remote origin, replacing your_username
with your actual GitHub username:
git remote add origin https://github.com/your_username/rails_memcache.git
That command tells Git where to push your code to.
Rename the default branch:
git branch -M main
And push your code to GitHub:
git push -u origin main
Your app’s code is now on GitHub, ready to be deployed to Render.
Deploy Rails to Render
Now that your code is on GitHub, deploying to Render is as simple as creating a new Blueprint Instance and connecting your GitHub repository.
Log in to Render and go to your Dashboard. Click New +, then click Blueprint.
Connect your GitHub account if you still need to do so. Then, find your repo in the Connect a repository section of the Create a new Blueprint Instance page and click Connect.
After clicking Connect you’ll be taken to a settings page. Choose a Blueprint Name. I’ll stick with rails_memcache.
Next, copy the value from your master.key
file and set it as the RAILS_MASTER_KEY
environment variable value.
Finally, click Apply to begin deploying.
If the web service deployment fails and you receive a notice An error has occurred
, click on the name of the web service to display its Events tab. You’ll see an event for the failed deployment. Click on deploy logs in the event to investigate.
When the deployment is live, go to your Render Dashboard, click on your Web Service, and finally click on its URL under the Web Service name to open it in your browser. The contact list app should work as it does locally.
Next, you’ll implement caching.
Set up caching in Rails
Setting up caching with Memcached in Rails involves the following steps:
- Create a Memcached-compatible cache
- Configure Rails to use your cache
Create a Memcached cache
In this tutorial, you’ll create a free Memcached-compatible cache with MemCachier. For another option to use Memcached on Render, read our blog post to learn how to run Memcached as a Render Private Service.
MemCachier is a fully managed caching service that simplifies setting up and using Memcached in your web applications. Built for seamless integration with cloud platforms like Render, MemCachier offers developers a streamlined and hassle-free way to implement high-performance caching in their applications without worrying about the complexities of managing a cluster of Memcached servers.
To begin, create a new MemCachier cache. Choose Render as the provider. Choose the same region as your Render Web Service. Choose the Free plan. Finally, click CREATE CACHE.

After creating your cache, you’ll find its configuration settings (Username, Password, Servers) on the CACHES dashboard.

On your Render dashboard, select your Web Service, then select the Environment tab. Then, add your MemCachier Servers, Username, and Password config values, naming the environment variables MEMCACHIER_SERVERS
, MEMCACHIER_USERNAME
, and MEMCACHIER_PASSWORD
, respectively.

Click Save Changes. Next, you’ll configure Rails to use your cache.
Configure Rails to use your cache
dalli
is a high-performance, pure Ruby client for accessing memcached servers. Add dalli
as a dependency in your Gemfile
:
# Gemfile
# ...
'dalli'
gem
:development do
group 'sqlite3'
gem # ...
In your terminal, install the added gem and update your Gemfile.lock
file:
bundle install
Now, configure your app’s default production cache store to use the cache store provided by dalli
by setting the config.cache_store
configuration option. Open config/environments/production.rb
in your code editor. Then, search for the commented-out line # config.cache_store = :mem_cache_store
and replace with the following:
# config/environments/production.rb
# ...
.cache_store = :mem_cache_store,
configENV["MEMCACHIER_SERVERS"] || "").split(","),
({:username => ENV["MEMCACHIER_USERNAME"],
:password => ENV["MEMCACHIER_PASSWORD"],
:failover => true,
:socket_timeout => 1.5,
:socket_failure_delay => 0.2,
:down_retry_delay => 60
}
# ...
For an explanation of the options, see the Dalli client options documentation.
Implement caching strategies in Rails
Rails provides fragment caching out-of-the-box. To add page and action caching, you need to add actionpack-page_caching
and actionpack-action_caching
to your Gemfile
. Rails’ official caching documentation is an excellent resource with in-depth explanations of the various Rails caching capabilities.
For fine-grained caching control, low-level caching is available, for example, for when you need to cache a particular value or database query result.
Fragment caching
Pages in Rails are generally built from various components. These components can be cached with fragment caching so they do not need to be rebuilt each time the page is requested.
For example, your /contacts
page is built from contact components, each showing
the name, the email, and three actions (show, edit, and destroy). We can cache
these fragments by adding the following to @contacts.each
loop in
app/views/contacts/index.html.erb
:
# app/views/contacts/index.html.erb
# ...
<% @contacts.each do |contact| %>
<% cache contact do %>
# ...
<% end %>
<% end %>
# ...
Fragment caching in Rails uses key-based expiration, or key-based invalidation, to make sure a cached fragment is kept up-to-date when its contents change.
Redeploy the app to Render with:
git add .
git commit -m 'Add fragment caching with Memcached'
git push
View Memcache statistics
To help demystify Memcache caching operations, it’s helpful to visualize what’s going on under the hood.
Though very cumbersome, one way to do that is to telnet
into a Memcached server and run the stats
command to see changes as operations are performed on your cache.
With MemCachier, however, you get an analytics dashboard that displays your cache’s statistics so you can monitor performance and troubleshoot issues quickly and easily.
To open your MemCachier analytics dashboard, log in to your MemCachier account, click Caches, then click the Analytics button for your cache.

With contact fragment caching in place, you’ll see a get hit
for each contact in your list each time you load the /contacts
page in the browser. Each time a contact is updated, you’ll set Set Cmds
increment as a new cache key is set for the updated fragment.
Session caching
Memcache can also be used as Rails’ session store. Memcache works well for storing information for short-lived sessions that time out. However, because Memcache is a cache and therefore not persistent, long-lived sessions are better suited to permanent storage options, such as your database.
To use your cache for session storage create the file config/initializers/session_store.rb
and add the following:
# config/initializers/session_store.rb
Rails.application.config.session_store :cache_store, key: '_rails_memcached_session'
Clean up
Once you finish this tutorial and no longer need your app, you can delete your Web Service and Database from the Render dashboard. You could also delete the corresponding Blueprint from Blueprints.
You can also delete your MemCachier cache from the Caches dashboard if you no longer need it.