Microservices at Twiga

Victor Mshindi
TwigaTech
Published in
6 min readOct 22, 2018

Twiga is one of the many companies that have decided to venture into the microservices world, to improve its web applications and deliver more value for the business while giving developers a chance to adventure into a brave new world. But before we talk about our microservices architecture, we must give context on what Twiga is and what it’s tech department does.

Twiga is a Kenyan B2B business that sources quality produce from farmers, and delivers it to vendors in Urban areas using a mobile-based, cashless supply platform to access distribution into the millions of small and medium-sized vendors in urban markets. We offer better prices to farmers and vendors while providing quality produce.

Twiga tech is the team that works on supporting all business processes with technology by building web-based solutions to improve operations and increase efficiency while solving simple and complex business problems. When first constituted the team set out to build a data management system(DMS), that would be used when sourcing for produce, handling payments and selling to vendors. Taking manual and tedious tasks and automating some aspects while significantly increasing data persistence. Giving us a seamless process and access to persistent data that allowed us to better manage and understand the business.

The Problem

The system got the job done and has played a significant role in Twiga’s growth over the years. Mainly because it allowed us to scale our business processes without losing money or quality. However, it had one problem that began to slow us down the bigger we grew. Which was that we built a monolithic web application, that became difficult to scale, maintain and lacked flexibility. It just wouldn’t scale as fast as the company and could have quickly become a major bottleneck for the entire organization. So because it wasn’t the right approach moving forward we opted to switch from a monolithic architecture to more modular architecture, specifically a microservices architecture. That would be used to build version two of our data management system. But before we talk microservices, we must first understand what a monolithic architecture is, and the disadvantages it brought in the Twiga context.

Monolith

A monolith is an application where everything is bundled as one, has a single code base with multiple modules and is designed to be self-contained. Modules are interconnected and interdependent in a very tightly coupled architecture. The key challenges the architecture presented to us were.

  • Increased risk per commit, due to the fact that it was difficult to update code or add a new feature, cause it could easily break the whole application and bring chaos.
  • Teams and developers also experienced less freedom, flexibility, and decreased velocity because many stakeholders are involved when a new feature is being added, this became very apparent when the team started growing.
  • Inefficient use of resources because if one particular module received a massive load of requests, we had to increase the VM resources, yet only one module needed the resources and not the entire application.
  • It was harder to maintain our codebase because of massive amounts code, and this was true especially if a module was not well documented. Also proving challenging to new team members who needed to understand the codebase before contributing.
  • The system was not stack or language agnostic, reducing our flexibility when building new modules.
  • All modules would interact with one database increasing load and query execution time. We also could not change or refactor table structures easily because it affected multiple modules.
  • Increased risk of system failure, because if one module failed there was a high chance that the whole service would collapse or failure would spread to other modules and lead to service disruption.
Our monolithic architecture

Microservices

Microservices are adequately defined by Sam Newman author of building microservices.

“Small autonomous services that work together, modeled around a business domain.” — Sam Newman

One could also say that it is a modular approach to software architecture that seeks to build services that are independent and loosely coupled. Thus reducing the risk that a change made within one element will cause unanticipated changes within another element. While optimizing around the autonomy of teams, increasing developer & team freedom, decentralizing power and creating a sense of ownership.

When we built the first iteration of DMS we considered using a microservices architecture but the risk of building an unstable application was too high. Because none of us had the experience and we needed to deliver value to the business as soon as possible, or as our CTO put it.

“The best way to guarantee application stability is through simplicity” — Caine Wanjau.

So we set out to build a simple application using the technologies, techniques, and practices that we knew, but with microservices at the back of our minds. Leading us to modularize version one while ensuring we made the app as loosely coupled as possible. This did not solve the monolith problem but eased the eventual transition.

Even though we modularized version one, we still needed to design the architecture of version two plus figure out what services would be created and with which technology. We chose not to make every feature a service but instead used domain driven design principles. To figure out which features were highly dependent on each other and whether they belonged in the same domain. Each domain then formed a service and so we crafted our architecture as seen in the image below.

Our microservices architecture

The Gateways and microservices run on a Kubernetes Cluster with each instance of the application running on a node. The API gateway deals with external requests, routing it to the appropriate service for execution. While the GraphQL gateway exists to abstract endpoints of all the microservices and providing one single endpoint.

On the service layer, each service is containerized and runs in a pod that is within a node. Which allows us to replicate services in accordance to load. Each service has its database allowing full ownership of its data and improved data persistence. It is also vital to note that services can be built with any stack since the architecture is language and stack agnostic.

RabbitMQ is then used to manage service to service communication via pub/sub. Giving us the ability to deal with task asynchronously and ensure all requests are handled without the requestor having to wait for a response. Also if a service dies while executing a job, it will be passed to another instance of the service.

The benefits of the architecture in the Twiga context are as follows.

  • Resilience — when one service fails, DMS v2 still runs, it won’t bring everything down with it. Certain features will be missing at times but this has allowed teams to find and fix problems faster.
  • DevOps — tools such as docker and Kubernetes are better suited for a modularized architecture thus we have been able to fully utilize them to automate builds, manage load and spin up new replicas, significantly increasing our application resilience.
  • Technology flexibility — the architecture is language and stack agnostic, which has allowed us to use different or the same stacks for a service, providing us with more freedom.
  • Easier to enhance — we can easily add a new feature or rework a service because they are not tightly coupled which has substantially reduced the risk per commit and stake holders. We are now currently able to push out new features in a shorter amount of time and have significantly increased developer velocity.

Thank you for reading, if you like what you read please drop a few claps and follow me and the publication. You can also find out more about Twiga at https://twiga.ke/

--

--