The CI/CD and DevOps Blog

REST API Best Practice: Assemble complex objects in the UI layer

I spent the first decade of my career at Microsoft. As a result, the only stack I was familiar with was Microsoft SQL Server at the backend, an API layer using SOAP + XML in the middle, topped with a web layer built on .Net. 

I was drunk on the SOAP kool-aid and completely ignored the inefficiencies created by SOAP + .NET. For example, the view state transferred for every interaction between the API and Web layer was very heavy and led to the following:

Complicated stored procedures: We tried to minimize calls between Web and API layers, which meant that any call that retrieved complex information from multiple tables needed a SQL Server stored procedure. 

Multiple APIs to manage CRUD: API contracts did not represent the DB schema and multiple CRUD APIs interacted with the same database object. This led to confusion among developers and frequent regression issues since it was difficult to find all code locations where an object was being created or updated.

Fragile database: The above issues made us reluctant to change anything in the database since it caused bugs and regressions. This meant our database was virtually frozen.

Having experienced this as a developer, manager, and eventually a Product Unit Manager, the first thing I did at Shippable was to pledge total allegiance to REST. One of the most important principles of REST is that every object should have an http routable method. Now this led us to a very interesting conundrum: where should we compose the objects that need to be displayed in the UI? Should we build a layer of finished APIs that return a ready-to-display object or should we compose the object in the UI layer by making multiple calls to the basic CRUD APIs?

Our journey to microservices: mono repo vs multiple repositories

Microservices are currently the hottest topic in software development. The concept is simple: Break down your application into smaller pieces that each perform a single business function and can be developed and deployed independently. These pieces, commonly called services, can then be assembled into an application using some flavor of service discovery like nginx or consul. The microservices approach is considered the architecture of choice for teams that want to build scalable platforms and efficiently and rapidly innovate on them. 

As infatuated as I am with this architecture, our journey to microservices was a long and winding road. It has finally led us to a version of the architecture that gives us the scalability and agility we require as a business. I want to share my thoughts, experiences, and lessons learned in a series of blogs around this topic so you may benefit from our experiences. Also, I would love to get your feedback or comments on our approach.

When you start moving to microservices, the first question before you write a single line of code is: How do you organize your codebase? Do you create a repository for each service, or do you create a single ‘mono repo’ for all services? The two approaches are illustrated below: