Since 2013, I’ve been developing and maintaining the MyClub codebase; a complex system designed to make managing events, club memberships, subscription payments, invoicing and member on-boarding and communication majorly simple for clubs.
MyClub was a PHP web application built on the CodeIgniter framework in its youth. It was accompanied by a MySQL database and lived on its own server. The only service-like component attached was the payment processing component which spoke to Stripe via API, but this all occurred server-side.
Over time, the members increased and the application began to struggle under the sheer load of the requests, so I moved it onto a cluster. Apache would point to a NFS mount-point with the application, uploads and associated requirements for the application to run. Soon began the issues.
When a user uploaded an image, it would move it to the appropriate folder and save the path to the database. However, by the time the server has performed the request and sent you to the next page, the image may not have been available for the other machine. Goodbye NFS & Apache cluster.
Soon came my challenge of migrating the horrific chunks of code that made up this application into smaller, manageable slices that would talk to the others. Microservices.
I had several main components that I could split up, but I needed them to communicate as much as possible. Billing, Authentication, Content, Communication and Management.
- Billing was fairly simple, it worked mostly off the database, but also integrates API calls to PayPal and Stripe; so I split this into two services: billing & payments.
- Authentication was a complex step. Not only did the application need to authenticate users on the front-end, but at the multiple endpoints across the web. For this, I create a logon and a session service. One lives by itself, and the other integrates with the base application.
- Content was simple. Take user-submitted content and ensure that it was stored in block storage and was accessible for the component that requested it. For this, I create an upload service and use Azure’s Blob storage service.
- Communication needed to replace PHP’s built-in mailer with an external service: I used Mandrill.
- Management was complex: not only do I need to track licenses, but also the load across the environments. The base application would now service a GUI that could talk to itself, but also these base components, so I needed to track which endpoints were making the most requests. Management was broken up into Scaling, an Azure Web App controller, a user management endpoint, an analytics service and finally an endpoint for merging all of the information contained within management.
As crude and small-scale as this project was, it makes it a ton easier to make changes to a specific component without affecting the rest of the components. Simply put: microservices make life easier.
Microservices make up most applications on the web or even mobile device. Treating individual ideas of the application like their own service makes it a tonne easier to manage. If the code is seperate, and an interface exists to link the two, then you’ve standardised the connection and you’ve standardised the endpoint. MyClub uses a combination of user-owned and club-owned data. When you make a payment, the user owns that payment receipt, but so does the club. Without creating redundancy, we store that receipt in the billing service and allow the club and the user to access it.
Although microservices can be seen as prematurely optimising your application, you should always strive to use them where you can. Amazon and Microsoft have made it infinitely cheaper to get started with application development in the cloud, so there’s no excuse that splitting your micro-app into microservices will become expensive.
I’ll probably write more about micro-services and converting monolithic applications into much smaller, manageable pieces in the future; but for now, focus on abstraction. Think of your idea; then break it down into smaller ideas. How can you split up those individual components into services and how can you make them talk to each other?