With puma
you can have concurrent requests. There are two concepts on how Puma can handle two incoming requests: Workers and Threads.
Workers
Puma can have multiple workers. Each worker is a process fork from puma and therefore a very heavy instance and can have multiple threads, that handle the incoming requests.
Example: A Puma server with 2 workers
and 1 thread
each can handle 2 request in parallel
. A third request has to wait until the thread of one of the workers is free.
Threads
Rails is thread-safe since version 4 (note that not all gems are thread-safe). This makes it possible to use threads in Puma to process multiple requests in a single worker. These requests are not processed in parallel, but once one thread is blocked, another can continue.
Example: A Puma server with 1 worker
and 2 threads
can handle 2 requests
. A third request has to wait until one of the two requests is finished.
Concurrent requests in development and tests
Normally having multiple threads for development is fine. Puma can handle blocking threads e.g. when you place a debugger only the current request is blocked and you can still visit other sites.
In case you want to request your own application in a request itself, Puma will not allow other threads to be processed. In this case you have a deadlock until you get a request Net::Timeout
from the inner request. You can fix it by setting the number of workers >= 2.
Example for the related config/puma.rb
:
workers Integer(ENV['WEB_CONCURRENCY'] || 2)
threads_count = Integer(ENV['RAILS_MAX_THREADS'] || 5)
Note: Having multiple workers in development and tests might cause unexpected issues (database transactions and other shared states), you should not enable it just for fun. Use bundle exec puma -t 0:1 -w 1 -p 3000
to debug concurrency issues.
Legacy
Settings like config.allow_concurrency = false
, config.threadsafe!
and config.middleware.delete Rack::Lock
seems not to be relevant for Rails >= 4 anymore.