Sinatra/Heroku microservices
I spent some of this weekend working on a side project. It began as a monolithic Sinatra app, then became two apps, and then finally the design settled on five microservices. At some point in this evolutionary journey I had a separate git repository for each microservice. But some of them wanted to share code, so I also had yet another git repository for each shared library, with the shared code included via git submodules.
This was a nightmare to work with, particularly as all of these git repositories were evolving simultaneously. So I wondered whether I could have a single git repository containing the code for all five microservices. But then how could I deploy them as separate Heroku apps? The answer lies in this Heroku article about managing multiple environments:
For simplicity, imagine we have a single git repository containing two Sinatra apps, stored in app_a.rb and app_b.rb. First, create a heroku app for each:
$ heroku create --remote app_a
...
$ heroku create --remote app_b
...
Now set an environment variable in each, telling it which of the two apps it is:
$ heroku config:set WHICH_APP=app_a --remote app_a
$ heroku config:set WHICH_APP=app_b --remote app_b
And finally in config.ru I configure Rack to start the app that matches the environment variable in each instance:
require 'rubygems'
service = ENV['WHICH_APP']
if ['app_a', 'app_b'].include?(service)
require File.join(File.dirname(__FILE__), service
run Sinatra::Application
else
abort "Unknown microservice '#{service}'"
end
Now, when I push to Heroku:
$ git push app_a master
$ git push app_b master
each Heroku app will launch a different Sinatra app.
Kevin Rutherford's Blog
- Kevin Rutherford's profile
- 20 followers

