Glad You're Ready. Let's Get Started!

Let us know how we can contact you.

Thank you!

We'll respond shortly.

Migrating from a single Rails app to a suite of Rails engines


We moved a Rails app into an unbuilt engine of a new blank slate container app to allow new parts of our app to live next to it as engines as well. It has been working great for us!

I have a sample app rails_container_and_engines of the result’s structure on github.

Skip to the pitfalls and discoveries section to read about some of the speed bumps we during our transition. Interested in the why and how? Read on!


As part of the project we had built a web app, a mobile app that talks to the web app’s API, two ETL tools to 1) do the initial data import from the app we were replacing and 2) get data into another of our client’s apps. At this point we knew that we would create one more big web app and several auxiliary apps.

Running up to the decision to using unbuilt engines we had several intense discussions on how to build loosely-coupled, highly-cohesive systems with Rails applications. We saw basically three choices:

  • All-in-one app that could get more structure through namespacing of its interals.
  • Services (REST or whatever, but) running as separate apps and communicating via APIs.
  • Engines running within a mostly feature-less container app.

The two big web apps share several models within the data access layer and use the same data. Because of this we chose the third option and left all of the apps within the same rails code base.

Internal discussions highlighted the costs/benefits of having all of these apps live within their own Rails project versus an engines approach. We feel that by using engines we are getting many of the benefits of a component based architecture without breaking Rails patterns. In addition, we feel that the cost of maintaining individual applications that share a central database or one giant application with less defined components would have been very high.

In order to make day to day development easier, and to avoid the “where do migrations live…” conversation and top level Rails deployment patterns, there is one twist to the architecture: everything resides in one git repo and engines are referenced from a single container application (similar to old school enterprise archive files). Each application is exposed via a unique context or resource identifier (each engine/app could also be isolated per instance via Apache). Here is the directory structure we ended up with:


Mike described this pattern in his recent blog posts Unbuilt Rails Dependencies: How to design for loosely-coupled, highly-cohesive components within a Rails application and Rails Contained: A Container for Web Application Development and Deployment. On how to make RubyMine work seamlessly with engines, read my post on IntelliJ Modules in Rubymine.

The steps we took

  • Generate a new, empty Rails app
  • Within the engines folder, create a new, mountable Rails engine
  • Copy all the tests from the original Rails app into the test directory and make them green.

    Ok. This step is a bit more involved. Essentially that’s it thought. Find some of the pitfalls we ran into described below. Here are a couple of highlights of what needs to happen:

    • Copy the files you need for a test to pass and namespace its class
    • Start with the model tests and work your way up towards integration and acceptance tests
    • Namespace everything with the name of the engine (either by fully qualifying every name – don’t do that) or with the lexical scope trick explained below. This includes tests and all classes.
    • Load needed gems explicitly: engines don’t load as much automatically as a Rails app
    • Namespace tables and assets
  • Copy the old .git directory into the new root folder in order to not loose any history. For us, git was not able to detect the changes as moves in many cases. This is certainly an area where you can improve on our solution!

For us, the real work started after this, when we started pullling out common code into a common models engine and began work on the second app.

We got all the tests to pass before we had namespaced any of the assets or rake tasks. That was an additional search-and-replace heavy step after the actual transition to an engine. It is not necessary right away if you do not have multiple applications at first, but to achieve the full effect, you will need to namespace the things as well.

Pitfalls and discoveries


Modules in your enige are not automatically loaded: make sure you reference them yourself before they are needed in other files.

Asset pre-compilation

Rails creates a default app/assets/stylesheets/application.css file which contains these lines:

/* ...
*= require_self
*= require_tree .

If you have this file in your main app, all css files will be compiled into one file. For us, this made almost everything look right. Almost. Little things broke here and there. Our app contained a couple of sections for which the stylesheets were meant to be loaded separately. Add files that you want to have precompiled as individual files to config.assets.precompile list to have them precompiled into separate files and solve this problem.

Are all your references and associations breaking?

Try this

module M
  class X
    def use_y
  class Y
    def self.do_it!

instead of

class M::X
  def use_y
class M::Y
  def self.do_it!

The first way sets the lexical scope to the module M as well as to the class Y and allows you to reference other classes in M without their full name. The second way sets the scope only to class M::Y and you have to fully qualify every class name to find it.

Don’t fight conventions

We were using fixture builder and while we were namespacing classes in modules we were trying to override the default table names to not be namespaced… Fixture builder didn’t like that at all. There may or may not be other dependencies that make leaving the conventions hard. So, save yourself the trouble and do the migrations (and stay consistent!) and namespace your tables as well!


They seem to be falling out of favor, which is probably a good thing. With engines they don’t seem to work (well). We ended up getting rid of our last two habtm relationships instead of trying to make them work. Creating the join as a class and adding the necessary has many :through relationships is straight forward enough.

We ended up with one production performance bug due to this: Rails

Engines depending on engines

We used kaminari for our pagination requirements. When our app first became an engine, kaminari stopped picking up our custom views. Instead it used its standard views. The load order got screwed up to which there are basically two solutions:

  • require => nil on both engines in the Gemfile and force the correct load order in your app, or…
  • avoid name clashes by namespacing your views (which you were going to do anyways, right?)

  1. Timur Vafin says:

    Hey, thank you for the sharing your exp with us.

    Could you please get more details how to each engine/app could also be isolated per instance via Apache?


  2. Stephan Hagemann says:

    Hi Timur,

    while I am not an expert on operations, I know that there are lots of ways to redirect to a specific server based on URL.

    Apache itself comes with [mod_proxy](, nginx has an [HttpRewriteModule]( [Wikipedia lists]( lots of ways to do this.

    In a larger setup, I’d probably integrate this kind of routing directly into the load balancer.


  3. Moha says:

    Thanks for the good article. I just reached thesame conclusion about 4 weeks ago before seeing your blog post.

    By unbuilt engine, what are you referring to? Is it an engine for which you did not run, ‘rake build’ or ‘gem build’.

  4. Stephan Hagemann says:

    Yes. I am calling these engines “unbuilt” as we are not compiling them into gems but instead keep them in the same code base and use them from within the same repository.

    Note, that we could decide to build the engines at some point in the future, e.g. if the development of any engine slowed down to the point where separating it into a new repository would be simpler than keeping the code in the same code base.

  5. Mike says:

    Nice and informative post. I was just wandering if you people are using backbone.js or ember.js or any frontend js mvc with the indivdual rails engine, because i am wondering if you initialize it once in the main app or they are initialized in each rails engine?


  6. Mike says:

    Sorry my 1st question seemed unclear, so i reframed it.
    Nice and informative talk on rails engines. I was just wandering how to use backbone.js or ember.js or any frontend js mvc across multiple rails engine. In a normal rails app, you will initialize the ember or backbone app once but i am wondering if they are initialized in each rails engine or how to do this?


  7. Stephan Hagemann says:

    Hey Mike,

    indeed, we are using backbone in one of our engines (and not in others). Having the ability to use different front end frameworks was one of the main drivers behind picking this approach.

    Checkout the [github repo]( You will see that all the folders under assets are namespaced. It is through that namespacing that an engine can load only the assets that it needs. I will update the repository to showcase this better.

    In that way, separating front end libraries per engine works even better than separating the back end gems: while our engines require different sets of gems, in production they are available to all, because everything is loaded within the same process.

  8. Mike says:

    Thanks for the response.

  9. Rodrigo Alvarez says:

    You say “We ended up with one production performance bug due to this: Rails”. Are you saying that moving from habtm to separate classes generated a bottleneck? Could you explain this a bit further?

    Thanks, great article!

  10. Stephan Hagemann says:

    Hi Rodrigo,

    It has been a while and I do not remember the details. What I do remember is that there was a change in the way certain queries were executed. That lead to a dramatic increase in query runtime in one use case. We fixed it by getting more control over the queries by turning habtm into explicit join classes.

  11. John Troxel says:

    Is is possible that the samples for namespacing are backwards? It seems like the two snippets don’t jibe with the discussion below them. Thanks.

  12. Stephan Hagemann says:

    John, you are of course right! Thanks for letting me know. I changed their order.

  13. Mark Burns says:

    Is that a typo in the example code?

    should the first class be “class M::X”?

    class M::Y
    def use_y
    class M::Y
    def self.do_it!

  14. Stephan Hagemann says:

    Mark, you’re right! Fixed.

  15. Jean Petit says:

    Hi Stephan,

    Great post ! Love the approach of keeping engines vendored and not fallling into the SOA trap as you share business logic between your apps.

    Say you have 3 engines (2 web apps and 1 API) sharing some data (a User model for example) which engine will hold the model ?


  16. Stephan Hagemann says:

    Hi Jean,

    Your model will have to go into yet another engine or gem that will be used by all three engines. Note, that you might have aspects of user that are not common to all engines and live in the web apps or the api directly.

    I go into detail on all of this in my talks: Also, my sample app has an example of this: “email_signup” (the model) is used by “teaser” (the web app).

    — Stephan

  17. Jean Petit says:

    Thanks, great work !

  18. Midhun Krishna says:

    Hi all,

    I have been following this post to convert my Rails Active Admin backend to a mountable engine, but I am stuck when trying to install Active Admin on to this engine without devise authentication using the –skip-user option [while running rake active_admin:install]. The host application for the engine has authentication configured using devise.

    But when accessing the name-spaced admin URL, the following error is raised:

    ActionController::RoutingError – uninitialized constant Admin::DashboardController:

    The same setting seems to work fine when used on a rails application without any mountable engine.

    Wondering whether anyone has anyone faced similar issues in the past and has any suggestion on what could be missing?


  19. Mathew John Kurishinkl says:

    Great Article.

  20. Stefan says:

    You rarely find articles on how to organize a large rails-codebase, good read!

    I still have some questions:

    – isn’t re-use the whole point of engines? What if you want to have a second app that re-uses one of the engines, what do you do?
    – how do you deal with engine-dependencies?
    – how does ci work? Do you have a central task to run all specs for all engines? Are engines ci’ed separately? Or all together? CI goes red when one of the engines goes red?
    – how about model-extensions? e.g. a basic user defined in engine A, additional fields (e.g. a link to a profile) added in engine B? We’re currently doing monkey-patching here, re-opening the model and adding the new fields, but we are not entirely happy with this, as it breaks often and creates very explicit dependencies….
    – is SOA a trap? Can you elaborate on that? We are currently using the engine-approach for re-use, but we end up with two sets of identical infrastructure for authentication/authorization: We were thinking about dropping engines and moving to an Oauth-based, centralized login/registration. With other services following(e.g. storage of large files/upload). You don’t think that this is a good idea?!

  21. Stephan Hagemann says:


    I have run into problems too when trying to get Active Admin to work inside of an engine. It does not seem to like not being included into a Rails app directly. Let me know if you make any progress!

  22. Stephan Hagemann says:


    To your points:

    – You can absolutely pull out and properly gemify every engine you use. I would urge you to not do so until you have to applications that use them to make development easier.
    – I don’t understand the question about engine-dependencies. All dependencies are handled through the gemspecs
    – CI: all of the above! You can have one suite that runs all tests. You can have one build per engine. There are a ton of options and what is best depends on what your app looks like.
    – Model-extensions: *don’t do it!!!* Try making every model the domain of one of you engines. Don’t reopen classes. As you have already discovered, the dependencies become really tight and understanding the code will become nontrivial really fast. If you need additional functionality for a class in another engine, consider putting it into some sort of collaborator object.
    – SOA is not necessarily a trap and it sounds like you have good reasons for why you want to switch certain things to an SOA. Because of the increased complexity of development I would suggest pushing a separation like that as far out as possible.

    I touched on a bunch of these questions in my last talk on the topic “Component-based Rails applications” –

  23. Soyou says:

    So, you change your links but forget to update them in this article. Very bad. Links should not break once they have been exposed to the world.

  24. Dave Woodall says:

    Hey Stephan,
    Thanks for putting this and MTN West talk together!

    I’m just now getting into the topic of engines and code organization.

    This is your warning that next time I see you, I’m going to pepper you with questions :-)

  25. Saurabh says:

    Can these engines use different databases?
    Suppose I want to use mongo for one engine and postgres for the other.

  26. Saurabh says:


    Can engines have their own database.

    In our case, we wanted SOA and we started with three different rails app. Now we want to merge these three apps using engines.
    But these apps use different db. One is using mongo and others are using postgres.
    I want that each engine should have their db and migration config within themselves.

    How can that be done?

  27. Stephan Hagemann says:

    Hi Saurabh,

    This is possible by making the database connections of the engines explicit and injection them into the engine configuration.

    In essence, you are just using Rails’ ability to set the ActiveRecord connection explicitly. There is a nice StackOverflow question about this:

    Also, look for the section “Connection to multiple databases in different models” in

  28. AnAn says:

    Good stuff Stephan! For those who haven’t yet played with engines – here’s a little tutorial for creating Rails API as an engine

Post a Comment

Your Information (Name required. Email address will not be displayed with comment.)

* Copy This Password *

* Type Or Paste Password Here *