This article is the third in a series that covers how the Mobile team at Swiggy built the Delivery Partner app. The first article covers the need, challenges involved, research conducted and how the team got together to build the new Delivery Partners app. The Second article covers identifying the requirements, tech evaluations and why we have chosen React Native.

In this article, we would like to give you a walkthrough of our core design principles, design patterns, high-level design of the app, scalability, real-time logs, metrics and stability of the application that we followed.

First things first: The Design principles

Keeping in mind to set good quality of the codebase standards, reusability of the code (we are lazy programmers!), futuristic approach (less rework), faster rollouts, A/B experimentation, plug-play-unplug use cases, unit testing, agility in integrating any 3rd party modules etc. we have laid out the below principles to stick to while building this app (Like how celestial bodies revolve around the Sun, our codebase revolves around these principles).

Core Design Principles (in-depth explanation below)

Keep it Simple and Stupid(KISS)

To maintain constant sync with our servers, our mobile application process needs to run in background for longer duration (on average 4–5 hours each session) and involves data such as tracking location info of our delivery partners (needed to assign trips, real-time tracking of an order, payment based on distance travelled etc.), order info (state of the order, item info, restaurant or store info, customer info etc.), earnings and incentives info etc. These components also interact with device resources such as GPS, network, bluetooth and other sensors for location tracking, proximity detection, distance travelled measurement, activity recognition etc. Performing these long-running/heavy operations on a single thread (UI / JS thread) isn’t efficient and in the long run, will become a bottleneck for UI operations inducing jittery/laggy experience. So, to keep things simple we decided to build only UI components in React native and long running, background intensive, data storage components in Native (Android/iOS)

Division of Components based on key criteria

Separation of Concerns

Our application is feature-rich and complex in serving the data needed to complete each delivery workflow. This involves handling user interactions, business logic, data sync and storage, network transactions, instrumentation of data such as user journey, touchpoints, real-time health metrics, etc. to name a few concerns. Instead of sprinkling these concerns all over the code base which becomes a developers nightmare to change/clean-up/revamp the code related to any concern, we separated these concerns either by creating a module or exposing a framework so that dependent modules can ignore the implementation details and be extensible to build upon.

Concerns involved in the App.

Modular and DRY (Do not repeat yourself)

At Swiggy, we are often working on multiple projects during which components that are built can be shared across multiple apps (Consumer, Delivery, Vendor, Daily etc.). Repeating the same code often involves development cycle, QA cycle, maintenance and stability monitoring, etc. To avoid these cycles and fast track production releases, we create components (however small it is) as agnostic to any specific application. So, based on this principle we decided to build below modules in which a couple of them are being shared across other apps.

Inversion of Control

According to the above principles, we built smaller components with clear responsibilities and separation of concerns. But as we build more components in the future, the interaction between these components, dependency resolution and the flow of control will be cumbersome . So, we relied on this principle which is analogous to the Hollywood principle:

“Don’t call us, we will call you”.