After being taxi drivers for over 20 years, Gwen Reynders and Wendy Steukers, owners of one of the biggest taxi companies in Hasselt, were up for a new challenge. With the arrival of Uber, Belgian taxi companies felt the competition, and Gwen and Wendy saw this as the perfect time to create a platform to unite and support all traditional taxi companies. That way they wanted to give the taxi companies the possibility to compete fairly. And so the transformation from being taxi drivers themselves to the proud owners of wave-a-cab began.
For wave-a-cab, we built both back- and front end. The fact that everything in the app depends on events, made it crucial that mobile and backend development were aligned at all times. Our developers had to work very closely together on the same features, and constant communication about API/model contracts was key throughout the building process.
“The back-end of the application is written in Symfony, a well-known PHP framework and supplemented by the administration portal created in Sulu. Both are fully customized to the clients` needs. Using a headless set-up empowered us to make the complex data structure manageable using an intuitive admin portal. All taxi companies, drivers, rides, payments, ... can be self-managed and followed up in case of any inconveniences.” says Sander Hofman, PHP developer at icapps.
In parallel complex operations concerning business logic are seamlessly executed in the background. While the initial idea was to build an app for Hasseltse Gele taxi, it quickly became a platform for all taxi companies in Flanders. By using Symfony we can easily manage this growth in both scalability and functionalities. At last, all data is properly presented to the mobile applications through a streamlined REST API.
The backend was built with a few minor hiccups along the way, but the overall process went really smoothly.
On a technological level wave-a-cab was rather complex consisting of the following components:
Client application (cross-platform)
Driver application (cross-platform)
Backend & Integrations
Besides the front-end we here focus solely on the backend of this project, consisting of the following parts:
The admin portal was set up using a headless CMS that allows us to develop the back- and front-end in a fully decoupled way. To build the admin interface, we used Sulu CMS fully customized to the clients’ needs. This administration portal is headless with an admin API in PHP and an admin UI in React. Using a headless set-up empowered us to make the complex data structure manageable while taking full advantage of the intuitive admin portal.
This resulted in a powerful platform enabling the client to self-manage taxi companies, drivers, clients, rides, payments,... and follow-up in case of inconveniences.
We created an API Platform that feeds both the data to the different mobile applications and our headless CMS. This API is fully REST-based embracing the OpenAPI specifications, which allowed us to create a centralized API combining data from numerous data providers.
The end users don't tend to provide feedback – if they are happy they won't let you know, if they are unhappy they'll probably just stop using the product. Metrics, insights, and analytics are therefore considered crucial in any backend system.
To maximize the quality assurance across our entire API Platform we tend to include a battle-tested set of Non-Functional Requirements or NFRs. Think of observability by the usage of a centralized logging system and monitoring services, enhancing traceability while using log aggregation with distributed IDs to keep track across our different systems. In combination with detailed API metrics, enabling us to scale and intervene when necessary.
The back-end consists of different APIs for both client and driver applications. Because of the complex business logic handling ride reservations, payments, bookings, and cancellations we take full advantage of Event-Driven Architecture. Every event is stored and tracked across its lifecycle, the event reflects every stage of an offline booking for which certain actions are triggered to inform and put in motion required dependencies.
This enables us to easily ingest incoming rides and enrich them with the relevant metadata while processing them in the extended checkout flow. This event-driven architecture is powered by RabbitMQ for processing relevant data at scale.
Pub/Sub is a messaging service that allows asynchronous communication between autonomous services or applications while using a publish-subscribe pattern. It is used to transfer data between our backend and mobile applications.
After authentication, a driver starts listening to a specific topic. When a client books a new ride for this specific driver, the ride is published on a specific topic on the queue. The mobile application gets notified about the new ride on the drivers’ queue and a specific callback is performed to accept and start the ride.
In addition to the streamlined API layer, our backend also functions as an aggregator between the different external services.
The payment flow is fully embedded throughout the mobile application and interacts with Mollie to handle ride payments in advance. So drivers don’t have to bother arranging them while finishing their rides. Every company that operates with wave-a-cab is registered on the Mollie platform and automatically handles incoming payments, refunds, and cancellations.
Exact Online is used by wave-a-cab as an Enterprise Resource Planning tool. In order to circumvent manual work all sales entries, documents and invoices are automatically created in Exact Online. Invoicing for other companies can also be manually triggered from the admin portal.
We use Firebase to send mobile push notifications to both drivers and clients.
To keep the cost low and the performance high, we implemented caching in multiple layers of the architecture. We cache the input data sources and output of our APIs. We apply HTTP caching combined with applicative caching all stored in Redis. We apply a fine granularity for the optimal balance between fast & fresh data. Next to that we also provided Elasticsearch for extensive and optimal searching. This provides an optimal experience for our end-user and keeps the load to a minimum.
The entire wave-a-cab project is hosted on Heroku, a cloud-based Platform-as-a-Service. Since wave-a-cab generates a certain amount of traffic, we rely on a multi-dyno set-up. With Elasticsearch, Redis, and RabbitMQ as the most utilized add-ons. All deployments are fully automated using our predefined CI/CD flow. This flow is responsible for installing, building, testing, and deploying our application to their dedicated environments.