Clearly, our app was desperately in need of a complete makeover. We wanted our drivers to have an equally good user experience as our consumers.

Tech

From a tech standpoint, there were some serious issues as well. Our app didn’t have a consistent and well-defined architecture in place. It was a pretty old legacy codebase we were working on. Things were quite cluttered (to put it lightly), which not only made it difficult to develop new features, but also to maintain existing ones.

With the existing architecture, it was quite difficult to support the scale at which Gojek was growing at the time.

Experience

And lastly, from an experience standpoint, things were not at their best as well. Here I am referring to the smoothness and stability of the app, and how efficiently it runs throughout the day.

For the driver app, there are a few unique challenges that made things a bit difficult for us:

- It is used by drivers on very low-end devices (512MB of RAM is not uncommon) - It is used continuously by our drivers for 10–12 hours every day - It needs to be battery-efficient and not drain the devices’ battery rapidly. Drivers have a tough time charging their phones multiple times a day, - It needs to consume minimum network data and work in areas with poor network connectivity as well

This was not something we could afford. It was time to roll up our sleeves and get to work.

These are some of the many challenges that make it quite difficult to provide an excellent and consistent user experience to all of our drivers across all devices and OS versions.

How It All Started

All of these things were bugging us for quite some time and we desperately wanted to do something about it. Making minor tweaks in our legacy codebase was not going to solve these problems. We needed something big, something fundamental — a “rewrite”.

The team was unanimously convinced that we needed a big rewrite. But we were not sure as to how we were going to pull this off given how big our app was and the new features we were continuously adding.

Approach #1: The Big Bang Rewrite

Initially, we were swayed by the idea of taking a fire-break and stopping all active development for a few months. We could use this time to work on rewriting the app and making it feature-neutral with what we already had.

Sounds stupid? Yes, it was.

Our app at that time was quite huge, consisting of a lot of features and user flows for different countries and services.

A quick estimation showed that it was nearly impossible to rewrite the entire app in 6–8 months, maybe even a year. And these were still highly optimistic estimations.

Positive people tend to overly underestimate things.

Also, not being able to build any features during this time would have a significant impact on our business which was something that we were not ready to afford at any cost. We wanted our tech to support our business and not jeopardise it.

So, this idea quickly went off the table.

Disclaimer — Big bang rewrites are not always bad. They do work sometimes depending on what stage your project is in or how big it is. If your project is small enough to be re-written in 2 weeks, sure, go ahead.

Approach #2: Progressive Reconstruction

We decided to redesign and rewrite the app incrementally, one feature at a time, making sure we do not stop any active feature development that our business needed.

But wait, what? This was like chasing a moving target where we will never be able to completely rewrite the entire app.

We decided to modify this idea slightly — we would dedicate approximately half of our resources towards rewriting the old features while the other half would continue building new features following our new design language and app architecture.

In this way, we would eventually be able to re-model (re-design + re-architect) the entire app.

We would also be able to make it to the market quickly, get early feedback from our drivers and make quick improvements. It was very important for us to make small but frequent releases so that we don’t get intimidated by the prospect of a big release.

Release early, release often. Be quick to the market.

This sounded like a solid plan for success and we decided to move ahead.

Getting The Foundation Ready

We knew we had a long journey ahead of us, so it was important for us to plan it thoroughly, right from the beginning.

We decided to start by rewriting the home screen and the booking flow of our app. Though the driver app has a lot of features, the booking flow is the core of it.

If you have a long journey ahead, make sure to plan it right.

Analysis

We took a few weeks to analyse how our tech stack would look, what architecture we were going to use, etc. We also had to think of properly managing the legacy code along with the new code in the same codebase.

It was important for us to ensure that our new code does what our existing code already did. As we were not the original authors of the existing code, it was difficult for us to get the edge cases right. Ideally, the existing code should have served as a spec and guided us on the rewrite, but in reality, this was far from the truth.

Make sure your new code does what your existing code already did.

As we were going to rewrite only a part of the codebase, we had to make sure that the existing features were perfectly compatible with the new ones. We needed to keep this compatibility layer simple and clean so that we could easily remove the legacy features in the future.

The idea was to cover as much as possible during this analysis phase and make sure that we set the sail in the right direction. But we also made sure to time-box this and not run into “analysis paralysis”.

If you spend too much time thinking about a thing, you will never get it done.

Estimation

This operation required a clear idea of when we would be able to release this new design to our drivers, so that we could align our business, operations, and other dependent teams accordingly. We defined the operation into clearly-defined granular tasks with individual estimates, figured out dependencies, and allocated developer bandwidth accordingly.