diff --git a/app/views/home/_stats.html.haml b/app/views/home/_stats.html.haml
index 7ad0df6ae..949a98008 100644
--- a/app/views/home/_stats.html.haml
+++ b/app/views/home/_stats.html.haml
@@ -1,4 +1,6 @@
-- cache("homepage_stats") do
+-# expires_in bounds staleness: expire_fragment only clears the cache of the
+-# process that handled the write, and the cache store may be per process.
+- cache("homepage_stats", expires_in: 12.hours) do
%p.stats
= t('.message_html',
member: link_to(t('.member_linktext', count: Member.confirmed.size.to_i), members_path),
diff --git a/config/environments/production.rb b/config/environments/production.rb
index 9bfa08117..4caba1b9e 100644
--- a/config/environments/production.rb
+++ b/config/environments/production.rb
@@ -51,15 +51,22 @@ Rails.application.configure do
# Prepend all log lines with the following tags.
config.log_tags = [:request_id]
- # Use a different cache store in production.
- config.cache_store = :mem_cache_store,
- (ENV["MEMCACHIER_SERVERS"] || "").split(","),
- { username: ENV.fetch("MEMCACHIER_USERNAME", nil),
- password: ENV.fetch("MEMCACHIER_PASSWORD", nil),
- failover: true,
- socket_timeout: 0.5,
- socket_failure_delay: 0.2,
- down_retry_delay: 60 }
+ # Memcached is opt-in via USE_MEMCACHED. Otherwise each process keeps its own
+ # capped in-memory cache: the store is per Puma worker, so the dyno pays
+ # RAILS_CACHE_SIZE_MB once per worker, not once in total.
+ memcached_servers = ENV.fetch("MEMCACHIER_SERVERS", "").split(",")
+
+ config.cache_store = if ENV["USE_MEMCACHED"] == "true" && memcached_servers.any?
+ [:mem_cache_store, memcached_servers,
+ { username: ENV.fetch("MEMCACHIER_USERNAME", nil),
+ password: ENV.fetch("MEMCACHIER_PASSWORD", nil),
+ failover: true,
+ socket_timeout: 0.5,
+ socket_failure_delay: 0.2,
+ down_retry_delay: 60 }]
+ else
+ [:memory_store, { size: Integer(ENV.fetch("RAILS_CACHE_SIZE_MB", "32")).megabytes }]
+ end
# Use a real queuing backend for Active Job (and separate queues per environment)
# config.active_job.queue_adapter = :resque