Being at the helm of a headless SaaS platform like Butterpaper, juggling the myriad demands of various sectors, from Fintech and AgriTech to Ecommerce, Analytics, and Research, is no small feat. As we grew and branched out, we soon found ourselves at the precipice of a decision - one that would alter our technology landscape. This is our story of how we embraced the microservices architecture, and the myriad insights we gathered along the journey.
In the throes of our rapid growth, we found ourselves evolving from a monolithic tech team that served our previous avatar very well, into an ecosystem of specialized product teams. Like rivers flowing from a lake, our once cohesive code began its journey across numerous Git repositories. Our deployment processes fragmented into more granular and focused pieces.
Take our last-mile fulfilment partner app (a.k.a. Driver or Logistic Partner App) as an example. It started as a nifty tool for drivers, providing navigational aid, managing recyclables from customers, and sharing ETAs. However, as the "so on" part of its features expanded to include safety features and telemetry, it was like watching our child grow up and take on multiple roles.
This growth spurt raised a question: Should we split the application? Was the time ripe for another microservice?
At first glance, you'd see two parts of our Driver App that behaved differently. One managed the trip states - heavy, transactional, and vital for smooth operations. The other dealt with telemetry data - high-frequency, ephemeral, and voluminous. With this dichotomy, we felt like parents realizing their twins had different interests and should be enrolled in separate schools.
Then came the question of database design. The dialogue around microservices often skirts this, focusing on the structure of services, their communication, and performance. But we wanted to get to the heart of the matter. It was not about merely replacing database calls with HTTP calls. It was about understanding if the application could split at the database level without sabotaging our network requests.
Microservices, like kids (and I have four of them), can be unpredictable. They might occasionally irritate you with their grumpiness (like when telemetry gathering goes down), but they also provide companionship and warmth (like the critical service managing trip states). The goal was not to love all microservices equally, but to ensure that any potential failure of the less critical ones didn't incapacitate the operationally essential ones.
As we strode forward on the microservices path, we remained mindful of not losing sight of the original purpose. It was not about independent deployment processes or development workflows. We were still one team, working on one product with one release cycle. The new microservices were just facets of our technical diamond.
The road to microservices is not always a straightforward path. There were moments of triumph and frustration, of deliberation and decision. We only added microservices when we felt the application's domain necessitated it. We evolved our technologies to support the distributed system and managed the complexity without overburdening our developers.
Our journey with microservices is far from over. We continue to enhance our testing, explore API gateways, and look into cross-service data aggregation via GraphQL. As we navigate these uncharted territories, we remain confident that our journey with microservices will lead us to a destination of growth and innovation. In this brave new world of tech, sometimes the destination is indeed the journey.