Rails application preloader
Pull request Compare This branch is 317 commits behind rails:master.
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Failed to load latest commit information.



Build Status Gem Version

Spring is a Rails application preloader. It speeds up development by keeping your application running in the background so you don't need to boot it every time you run a test, rake task or migration.


  • Totally automatic; no need to explicitly start and stop the background process
  • Reloads your application code on each run
  • Restarts your application when configs / initializers / gem dependencies are changed


  • Ruby versions: MRI 1.9.3, MRI 2.0, MRI 2.1
  • Rails versions: 3.2, 4.0

Spring makes extensive use of Process.fork, so won't be able to provide a speed up on platforms which don't support forking (Windows, JRuby).



Add spring to your Gemfile:

gem "spring", group: :development

It's recommended to 'springify' the executables in your bin/ directory:

$ bundle install
$ bundle exec spring binstub --all

This generates a bin/spring executable, and inserts a small snippet of code into relevant existing executables. The snippet looks like this:

  load File.expand_path("../spring", __FILE__)
rescue LoadError

On platforms where spring is installed and supported, this snippet hooks spring into the execution of commands. In other cases, the snippet will just be silently ignored and the lines after it will be executed as normal.

If you don't want to prefix every command you type with bin/, you can use direnv to automatically add ./bin to your PATH when you cd into your application.


For this walkthrough I've generated a new Rails application, and run rails generate scaffold posts name:string.

Let's run a test:

$ time bin/rake test test/functional/posts_controller_test.rb
Run options:

# Running tests:


Finished tests in 0.127245s, 55.0121 tests/s, 78.5887 assertions/s.

7 tests, 10 assertions, 0 failures, 0 errors, 0 skips

real    0m2.165s
user    0m0.281s
sys     0m0.066s

That wasn't particularly fast because it was the first run, so spring had to boot the application. It's now running:

$ bin/spring status
Spring is running:

26150 spring server | spring-demo-app | started 3 secs ago
26155 spring app    | spring-demo-app | started 3 secs ago | test mode

The next run is faster:

$ time bin/rake test test/functional/posts_controller_test.rb
Run options:

# Running tests:


Finished tests in 0.176896s, 39.5714 tests/s, 56.5305 assertions/s.

7 tests, 10 assertions, 0 failures, 0 errors, 0 skips

real    0m0.610s
user    0m0.276s
sys     0m0.059s

If we edit any of the application files, or test files, the changes will be picked up on the next run without the background process having to restart. This works in exactly the same way as the code reloading which allows you to refresh your browser and instantly see changes during development.

But if we edit any of the files which were used to start the application (configs, initializers, your gemfile), the application needs to be fully restarted. This happens automatically.

Let's "edit" config/application.rb:

$ touch config/application.rb
$ bin/spring status
Spring is running:

26150 spring server | spring-demo-app | started 36 secs ago
26556 spring app    | spring-demo-app | started 1 sec ago | test mode

The application detected that config/application.rb changed and automatically restarted itself.

If we run a command that uses a different environment, then that environment gets booted up:

$ bin/rake routes
    posts GET    /posts(.:format)          posts#index
          POST   /posts(.:format)          posts#create
 new_post GET    /posts/new(.:format)      posts#new
edit_post GET    /posts/:id/edit(.:format) posts#edit
     post GET    /posts/:id(.:format)      posts#show
          PUT    /posts/:id(.:format)      posts#update
          DELETE /posts/:id(.:format)      posts#destroy

$ bin/spring status
Spring is running:

26150 spring server | spring-demo-app | started 1 min ago
26556 spring app    | spring-demo-app | started 42 secs ago | test mode
26707 spring app    | spring-demo-app | started 2 secs ago | development mode

There's no need to "shut down" spring. This will happen automatically when you close your terminal. However if you do want to do a manual shut down, use the stop command:

$ bin/spring stop
Spring stopped.


To remove spring:

  • 'Unspring' your bin/ executables: bin/spring binstub --remove --all
  • Remove spring from your Gemfile



Runs a rake task. Rake tasks run in the development environment by default. You can change this on the fly by using the RAILS_ENV environment variable. The environment is also configurable with the Spring::Commands::Rake.environment_matchers hash. This has sensible defaults, but if you need to match a specific task to a specific environment, you'd do it like this:

Spring::Commands::Rake.environment_matchers["perf_test"] = "test"
Spring::Commands::Rake.environment_matchers[/^perf/]     = "test"

# To change the environment when you run `rake` with no arguments
Spring::Commands::Rake.environment_matchers[:default] = "development"

rails console, rails generate, rails runner

These execute the rails command you already know and love. If you run a different sub command (e.g. rails server) then spring will automatically pass it through to the underlying rails executable (without the speed-up).

Additional commands

You can add these to your Gemfile for additional commands (run spring stop afterwards to pick up the changes):

Use without adding to bundle

If you don't want spring-related code checked into your source repository, it's possible to use spring without adding to your Gemfile. However, using spring binstubs without adding spring to the Gemfile is not supported.

To use spring like this, do a gem install spring and then prefix commands with spring. For example, rather than running bin/rake -T, you'd run spring rake -T.


Spring will read ~/.spring.rb and config/spring.rb for custom settings. Note that ~/.spring.rb is loaded before bundler, but config/spring.rb is loaded after bundler. So if you have any spring-commands-* gems installed that you want to be available in all projects without having to be added to the project's Gemfile, require them in your ~/.spring.rb.

Application root

Spring must know how to find your Rails application. If you have a normal app everything works out of the box. If you are working on a project with a special setup (an engine for example), you must tell Spring where your app is located:

Spring.application_root = './test/dummy'

Running code before forking

There is no Spring.before_fork callback. To run something before the fork, you can place it in ~/.spring.rb or config/spring.rb or in any of the files which get run when your application initializers, such as config/application.rb, config/environments/*.rb or config/initializers/*.rb.

For example, if loading your test helper is slow, you might like to preload it to speed up your test runs. To do this you could add the following to your config/environments/test.rb:

config.after_initialize do
  require Rails.root.join("test/helper")

Running code after forking

You might want to run code after Spring forked off the process but before the actual command is run. You might want to use an after_fork callback if you have to connect to an external service, do some general cleanup or set up dynamic configuration.

Spring.after_fork do
  # run arbitrary code

If you want to register multiple callbacks you can simply call Spring.after_fork multiple times with different blocks.

Watching files and directories

Spring will automatically detect file changes to any file loaded when the server boots. Changes will cause the affected environments to be restarted.

If there are additional files or directories which should trigger an application restart, you can specify them with Spring.watch:

Spring.watch "spec/factories"

By default Spring polls the filesystem for changes once every 0.2 seconds. This method requires zero configuration, but if you find that it's using too much CPU, then you can turn on event-based file system listening:

Spring.watch_method = :listen

You may need to add the listen gem to your Gemfile.


If you want to get more information about what spring is doing, you can specify a log file with the SPRING_LOG environment variable:

spring stop # if spring is already running
export SPRING_LOG=/tmp/spring.log
spring rake -T