How Emarsys Approaches Service Sizing on Heroku

Based in Budapest, Hungary, Andras Fincza (Head of Engineering) and Rafael Ördög (Technical Lead) work for Emarsys, a global marketing automation platform. Read our Emarsys customer story to learn more about their migration experience on Heroku.

How did you introduce microservices at Emarsys?

We take an evolutionary approach to our architecture. Our marketing automation platform was originally designed as a monolithic system built in PHP and MySQL and running on in-house infrastructure. We were running two major services on our in-house infrastructure: one for HDS (historical data service) and the other for smart insights and analysis. However, it was hard to grow the platform effectively because it required heavy support from our system engineering resources. Our system engineers were regularly inundated with requests, and it took a while to make any changes.

In late 2014, we started experimenting with a service-oriented architecture to ease the burden on system engineering and allow us to experiment with new technologies. We wanted the ability to deploy and scale some features independently. We also wanted to try different languages and data stores without adding an extra burden on our system engineering team.

We decided to pilot a small, non-critical microservice which would funnel user behavior data into our main application. We considered several options, but in the end we chose to run our pilot on Heroku. We were able to run it successfully without system engineering support, and our management agreed to let us go further in the direction of a service-oriented architecture. We moved more non-critical services to the cloud, and now we are running more and more critical services on Heroku.

Based on our experience, we established a goal of having only “no ops teams” in the future. These teams would be able to develop and manage individual services themselves, without having to rely on system engineering. Running our apps on Heroku has both eased the burden on system engineering as well as allowed us to more effectively plan and control costs.

Do you still develop on the legacy app?

We still maintain the legacy app and add new things on occasion. It’s hard to split off some large feature sets from the monolithic app, and we find that the legacy infrastructure is better suited to some services. But most of our teams are now developing on Heroku. As we are planning new features, we’ll create them as feature services on Heroku whenever possible. We currently have 150+ services on Heroku with 42 services in production.

With the current trend toward microservices, how do you approach service sizing?

We call our services “feature services” rather than “microservices” because they have a broader scope and context than a typical microservice. Each is essentially a full stack service with an independent front and back end. For example, user management is not just about managing users, but also about managing invitation emails, lost passwords, etc.

We took this approach because we were afraid that if we had hundreds or even thousands of microservices, they’d be extremely difficult to manage. So the broader scope of “feature services” works much better for us.

However, it’s not only about the amount of services we moved to the cloud, but also about the architecture of specific services as well. When setting up our services, we keep in mind that they might have to be split up if they get too big. For example, we currently have a service that provides reporting UIs, but it is also responsible for storing data. If the data gets too big, we can split it off to our data warehouse and maintain a very lightweight service for serving data and a separate service that is only for providing the UI as a real backend for the front end. When we saw that it was not so good to have big service call chains, we started to cache and use internal data stores to provide very fast experiences for users.

How do you handle security and communication between services?

Our services communicate mostly through REST APIs, but some also use RabbitMQ message queues. To keep service chains very short, we want only some services to respond to requests. Within our legacy app, we open an iFrame or use Javascript to bring in the feature service to create a seamless single-page app UX.

Security is critical for us. In order to ensure security between services, we developed a stateless HTTP request signing library called Escher, which is a version of the authentication library from AWS Signature Version 4, to sign every request between services.

What else can you tell us about your stack?

We are early adopters of many things. Our organization has a rule: as long as your team can build it, troubleshoot it, and operate it without system engineering resources, then our management is willing to let you run a pilot project. Heroku has enabled us to experiment more freely.

Since our services are full stack, we can use whatever language we think is best. We’ve been using a lot of Javascript and Node.js, along with MongoDB, Heroku Redis, Heroku Postgres, and SQL. We’d been using AngularJS since 1.1 and now we’re testing Angular 2 beta.

From our first experiments on Heroku, we’ve pioneered many new technologies for Emarsys. In addition, many engineers outside of our company are also interested in learning more about our experience with technologies such as Angular 2. As part of the JSConf Budapest in May 2016, Andras Fincza and colleagues ran a sold-out workshop entitled: “A Journey Towards Angular 2.” Due to popular demand, the workshop will be repeated soon.

Browse the blog archives, subscribe to the full-text feed, or visit the engineering blog.