Portable parking meter in your pocket
Founded in 2010, Parkster has quickly become one of the fastest growing digital parking services in Sweden. Their vision is to make it quick and easy for you to pay your parking fees with your smartphone, via your Parkster app, SMS or voice mail. They want to see a world where you don’t need to guesstimate the required parking time or stand in line waiting by a busy parking meter. It should be easy to pay for parking - for everyone, everywhere. Moreover, Parkster doesn't want the customer to pay more when using tools of the future - that’s why there are no extra fees if you are using Parkster’s app when parking.
Breaking up a tightly coupled monolithic application
Like many other companies, Netflix just to mention one, Parkster started out with a monolithic architecture. They wanted to have their business model proven before they went further. A monolithic application is where the whole application is built as a single unit. All code for a system is in a single codebase that is compiled together and produces a single system.
Having one codebase seemed easiest and quickest at the time.
Having one codebase seemed as the easiest and quickest solution at the time, and solved their core business problems, which included connecting devices with people, parking zones, billing, and payments. A few years later, they decided to break up the monolith into multiple small codebases. Which they did through multiple microservices communicating via message queues.
Parkster tried out their parking service for the first time in Lund, Sweden. After that, they rapidly expanded into more cities and introduced new features. The core model grew and components became tightly coupled.
Deploying the codebase meant deploying everything at once. One big codebase made it hard and difficult to fix bugs and to add new features. A deep knowledge was also required before doing an attempt for a single small code change, no one wants to add new code that could disrupt operation in some unforeseen way. One day they had enough - the application had to be decoupled.
The biggest reason we moved from monolith to microservice were decoupling.
Parkster’s move from a monolith architecture to a microservice architecture is right now in working progress. They are breaking up their software into a collection of small, isolated services, where each service can independently deploy and scale as needed - independently of other services. Their system today has about 15-20 microservices, where the core app is written in Java.
They are already enjoying their changes: “It's very nice to focus on a specific limited part of the system instead of having to think about the entire system, every time you do something new or make changes. As we grow, I think we will benefit even more from this change.” said Anders Davoust, developer at Parkster.
Breaking down their codebase has also given the software developers the freedom to use whatever technologies that make sense for a particular service. Different parts of the application can evolve independently, be written in different languages and/or maintained by separated developer teams. For example, one part of the system uses MongoDB and another part uses MySQL. Most code is written in Java, but parts of the system are written in Clojure. Parkster is using the open-source system Kubernetes as container orchestration platform.
Resiliency - The capacity to recover quickly from difficulties
Applications might be delayed or crash sometimes - it happens. It could be due to timeouts or that you simply have errors in your code that could affect the whole application.
Another thing Parkster really like about their system today is that it can still be operational even if part of the backend processing is delayed or broken. Everything will not break just because one small part of the system is not operating as it should. By breaking up the system into autonomous components, Parkster inherently created more resiliency.
Message queues, RabbitMQ and CloudAMQP
Parkster is separating different components via message queues. A message queue may force the receiving application to confirm that it has completed a task and that it is safe to remove the task from the queue. The message will just stay in the queue if anything fails in the receiving application. A message queue provides a temporary message storage when the destination program is busy or not connected.
The message broker used between all microservices in Parkster is RabbitMQ. “It was a simple choice - we had used RabbitMQ in other projects before we built Parkster and we had a good experience of RabbitMQ.” The reason they went for CloudAMQP, a hosted RabbitMQ solution, was because they felt that CloudAMQP had way more knowledge about management of RabbitMQ than they had. They simply wanted to put their focus on the product instead of spending days configuring and handling server setups. CloudAMQP has been at the forefront when it comes to RabbitMQ server configurations and optimization since 2012.
I asked what they like about CloudAMQP, and I received a quick answer: “I love the support that CloudAMQP gives us, always quick feedback and good help”.
I love the support that CloudAMQP gives us, always quick feedback and good help.
Now, Parkster’s goal is to get rid of the old monolithic repo entirely and focus on a new era where the whole system is built upon microservices.
Thanks for your time Anders Davoust, it was a pleasure talking to you!