Over a million developers have joined DZone.

Architecting Rails Apps as Microservices

Learn about architecting Rails apps as microservices: whether you should build as an SOA, how teams should be organized, and how components scale.

· Integration Zone

Build APIs from SQL and NoSQL or Salesforce data sources in seconds. Read the Creating REST APIs white paper, brought to you in partnership with CA Technologies.

Rails apps come in many shapes and sizes. On the one hand, you have large monolithic applications where the entire application (admin, API, front-end, and all the work it needs to perform) is in a single place. On the other end of the spectrum, you have a series of microservices, all communicating with each other with the goal of breaking up the work into more manageable chunks.

This use of microservices is what’s called Service Oriented Architecture (SOA). Rails apps from what I have seen tend to lean toward being monolithic, but there is nothing stopping a developer from having multiple Rails apps which work together and/or connecting to services written in other languages or frameworks to help them accomplish the task at hand.

Rails apps tend to be monolothic, but there’s no reason you can’t architect them as microservices.


Monoliths don’t need to be written poorly, but poorly written monoliths broken up into microservices will most likely end up being poorly written as well. There are several ways you can write your app which will not only help you write cleaner (and more easily testable) code, but will also help you if/when the need arises to break up the application.

Our Use Case for a Rails App with Microservices

For this article, we’ll be talking about building a website that is a CMS. Imagine any large newspaper or blog that has multiple writers contributing articles with users that can subscribe to receive alerts about certain topics.

Martin Fowler wrote a great article on why editing and publishing should be separated into two different systems. We’re taking that example and adding two more components: Notifications and Subscribers.

The CMS we’re talking about has four main components:

  • CMS Editor: Used by writers and editors to create, edit, and publish articles.
  • Public Website: Used by the public to view published articles.
  • Notifier: Used to notify subscribers of new published articles.
  • Subscribers: Used to manage user accounts and subscriptions.

CMS system

Should I Build My Rails App as an SOA?

So how do you decide if it makes more sense to build your Rails app as a monolith or to build it using microservices? There is no right or wrong answer, but asking yourself the following questions may help you decide.

How do you decide whether to build your Rails app as a monolith or using microservices?


How Are My Teams Organized?

Deciding to go with an SOA often has very little to do with technical reasons but rather how the different development teams are organized.

It may make more sense for four teams to each take one of the major components to work in a silo than to have everyone working on a single system. If you’re working on a team of just a few developers, deciding to start right from the beginning with microservices may actually decrease development speed by adding the increased flexibility of having four different systems communicate with one another (and deploy).

Do Different Components Scale Differently?

There’s a good chance that in our use-case system in this article, the Public Website will have a lot more traffic to it than the CMS Editor that the writers and editors will be using.

By building them as separate systems, we can scale them independently and/or apply different caching techniques for the different parts of the system. You can still scale the system as a monolith, but you would be scaling the entire thing at once, rather than the different components individually.

Do Different Components Use Different Technologies?

You may want to build your CMS Editor as a Single Page Application (SPA) with React or Angular and have the main public facing website be more of a traditional server-rendered Rails app (for SEO purposes). Maybe the Notifier would be better suited as an Elixir app due to the language’s concurrency and parallelism support.

By having them as different systems, you’re free to choose the best language for the job in each of the services.

Defining Boundaries

The most important part in all of this is that there are well-defined boundaries between the different components of the system.

One part of the system should think of itself as the Client communicating to an externalServer. It doesn’t matter if the communication happens through method calls or over HTTP, it just knows that it has to talk to another part of the system.

One way we can do this is through defining clear boundaries.

Let’s say that when an article is published two things need to happen:

  1. First that we send the published version of the article to the Public Website, which will return to us a URL that it is published at.
  2. Second that we send the newly created public URL, the topic, and the title to the Notifierwhich will handle notifying all interested subscribers. This second task can be done asynchronously because it may take a while to notify everyone, and there isn’t really a response that we need back.

For example, take the following code which publishes an article. The article doesn’t really know whether the service being called is simply a method call or if it is an HTTP call.

class Publisher 
  attr_reader :article, :service

  def initialize(article, service) 
    @article = article 
    @service = service 

  def publish 
    mark_as_published call_service 


  def call_service 
      author: article.author, 
      title: article.title, 
      slug: article.slug, 
      category: article.category, 
      body: article.body 

  def mark_as_published(published_url) 
    article.published_at = Time.zone.now 
    article.published_url = published_url 

This type of coding also allows us to easily test the Publisher class’ functionality by using a TestPublisherService which returns canned answers.

require "rails_helper"

RSpec.describe Publisher, type: :model do

  let(:article) { 
      author: 'Carlos Valderrama', 
      title: 'My Hair Secrets', 
      slug: 'my-hair-secrets', 
      category: 'Soccer', 
      body: "# My Hair Secrets\nHow hair was the secret to my soccer success." 

  class TestPublisherService < PublisherService 
    def call 

  describe 'publishes an article to public website' do 
    subject { Publisher.new(article, TestPublisherService) }

    it 'sets published url' do
      published_article = subject.publish
      expect(published_article.published_url).to eq('http://www.website.com/article/my-hair-secrets')
    it 'sets published at' do
      published_article = subject.publish
      expect(published_article.published_at).to be_a(Time)

In fact, the implementation of the PublisherService hasn’t even been built yet, but it doesn’t stop us from writing tests to ensure that the client (in this case the Publisher) works as expected.

class PublisherService 
  attr_reader :author, :title, :slug, :category, :body

  def initialize(author:, title:, slug:, category:, body:) 
    @author = author 
    @title = title 
    @slug = slug 
    @category = category 
    @body = body 

  def call 
    # coming soon 

Service Communication

Services need to be able to communicate with each other. This is something as Ruby developers we’re already familiar with even if we haven’t built microservices before.

When you “call” the method of an Object, what you’re really doing is sending a message to it, as can be seen by changing Time.now to Time.send(:now). Whether the message is sent via a method call or whether the communication happens over HTTP, the idea is the same. We’re wanting to send a message to another part of the system, and often we want a response back.

Communication Over HTTP

Communicating over HTTP is a great way to send messages to a service when you need an instant response — when you’re relying on receiving a piece of data back to continue program execution.

HTTP is a great way to send messages to a service when you need an instant response.


I’ve taken the original PublisherService class and have implemented an HTTP post to our service using the Faraday gem.

class PublisherService < HttpService
  attr_reader :author, :title, :slug, :category, :body

  def initialize(author:, title:, slug:, category:, body:)
    @author   = author
    @title    = title
    @slug     = slug
    @category = category
    @body     = body

  def call


  def conn
    Faraday.new(url: Cms::PUBLIC_WEBSITE_URL)

  def post
    resp = conn.post '/articles/publish', payload

    if resp.success?
      JSON.parse resp.body
      raise ServiceResponseError

  def payload
    {author: author, title: title, slug: slug, category: category, body: body}

Its job is to build the data that will be posted to the service and handle its response. It also verifies that the response is a success and will raise an exception otherwise. More on that later.

I’ve used the constant Cms::PUBLIC_WEBSITE_URL, which gets its value through an initializer. This allows us to configure it using ENV variables for the different environments we end up deploying our app to.

Cms::PUBLIC_WEBSITE_URL = ENV['PUBLIC_WEBSITE_URL'] || 'http://localhost:3000'

Testing Our Services

Now it’s time to test that our PublisherService class works correctly.

For this I don’t recommend making an actual HTTP call; that would slow down testing and require that you have the service up and running at all times on your development machine (or continuous integration server). For this we can use the WebMock gem to intercept the HTTP call and get the required response.

RSpec.describe PublisherService, type: :model do

  let(:article) {
      author:   'Carlos Valderrama',
      title:    'My Hair Secrets',
      slug:     'my-hair-secrets',
      category: 'Soccer',
      body:     "# My Hair Secrets\nHow hair was the secret to my soccer success."

  describe 'call the publisher service' do
    subject {
        author:   article.author,
        title:    article.title,
        slug:     article.slug,
        category: article.category,
        body:     article.body

    let(:post_url) {

    let(:payload) {
      {published_url: 'http://www.website.com/article/my-hair-secrets'}.to_json

    it 'parses response for published url' do
      stub_request(:post, post_url).to_return(body: payload)
      expect(subject.call).to eq('http://www.website.com/article/my-hair-secrets')

    it 'raises exception on failure' do
      stub_request(:post, post_url).to_return(status: 500)
      expect{subject.call}.to raise_error(PublisherService::ServiceResponseError)


Planning for Failure

There will inevitably come a time when the service is down or times out, and we need to handle that error.

It’s really up to the developer to decide what needs to be done when the service is down. Can the website continue to work when it’s down? In the case of our CMS application, it can work fine for creating and editing articles, but we’ll have to show an error to the user when they attempt to publish an article.

As part of the test above, there is a case that looks for a 500 response from the server and checks to ensure it raises the PublisherService::ServiceResponseError exception. This error comes from its parent class, HttpService, which for now doesn’t contain much other than the error classes.

class HttpService

  class Error < RuntimeError

  class ServiceResponseError < Error


In another article by Martin Fowler, he talks about a pattern called the CircuitBreaker, whose job it is to detect when a service is misbehaving and to avoid making a call that would most likely end up in an error anyway.

Another technique that can be used to make our application more resilient is to make it aware of the status of the different services that it needs to function.

This could be controlled manually by developers, giving them the ability to turn off certain website functionality when a service is known to be down and avoiding errors altogether. However, it could also be controlled in conjunction with some sort of CircuitBreaker pattern programmatically.

Before showing the Publish button to your users, a quick check to PublisherService.available? will help avoid errors.

Communication With Queues

HTTP isn’t the only way to communicate to other services. Queues are a great way to pass asynchronous messages back and forth between the various services. The perfect situation for this is when you have some work that you want done but you don’t need a direct response back from the receiver of this message (sending emails for example).

Queues are a great way to pass asynchronous messages back and forth between services.


In our CMS app, after an article is published, any subscribers to that article’s topic are notified (either through email, a website alert, or push notification) that there is a new article that might be of interest to them. Our app doesn’t need a response back from the Notifierservice, it just needs to send a message to it and let it do its work.

This article was written by Leigh Halliday

The Integration Zone is brought to you in partnership with CA Technologies.  Use CA Live API Creator to quickly create complete application backends, with secure APIs and robust application logic, in an easy to use interface.

integration,enterprise integration,ei,microservices,rails,ruby

Published at DZone with permission of Moritz Plassnig, DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

The best of DZone straight to your inbox.

Please provide a valid email address.

Thanks for subscribing!

Awesome! Check your inbox to verify your email so you can start receiving the latest in tech news and resources.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}