Courier user interface in-depth — photos

By | 28/08/2022

Image source:

Architecture and Design Principles Behind the Swiggy’s Delivery Partners app

This article is the 3rd 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 commodity covers identifying the requirements, tech evaluations and why nosotros take chosen React Native.

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

Offset 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 arroyo (less rework), faster rollouts, A/B experimentation, plug-play-unplug utilize cases, unit testing, agility in integrating any third party modules etc. nosotros accept laid out the beneath principles to stick to while edifice this app (Similar how celestial bodies revolve effectually the Sun, our codebase revolves around these principles).

Core Design Principles (in-depth explanation beneath)

Keep it Simple and Stupid(KISS)

To maintain constant sync with our servers, our mobile
application procedure needs to run in background for longer duration
(on average iv–5 hours each session) and involves data such as tracking

location info

of our commitment partners (needed to assign trips, existent-time tracking of an order, payment based on distance travelled etc.),
club info
(state of the order, item info, restaurant or shop info, customer info etc.),
earnings and incentives info

etc. These components too collaborate with device resources such every bit
GPS, network, bluetooth and other sensors
for location tracking, proximity detection, distance travelled measurement, activeness recognition etc. Performing these long-running/heavy operations on a single thread (UI / JS thread) isn’t efficient and in the long run, will get a bottleneck for UI operations inducing jittery/laggy experience. So, to go on things unproblematic we decided to build only

UI components in React native and long running, background intensive, information 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 consummate each delivery workflow. This involves handling user interactions, business logic, information sync and storage, network transactions, instrumentation of information such as user journeying, 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 alter/make 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 (Practise 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 aforementioned code frequently involves evolution cycle, QA cycle, maintenance and stability monitoring, etc. To avoid these cycles and fast track product releases, nosotros create components (yet minor it is) equally agnostic to whatever specific awarding. 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 to a higher place principles, we built smaller components with clear responsibilities and separation of concerns. But
as we build more than components in the future, the interaction between these components, dependency resolution and the menstruation of control will be cumbersome. So, we relied on this principle which is coordinating to the Hollywood principle:

“Don’t call us, we volition call yous”.

Based on this principle, the flow of control is handled by the external components rather than the caller to reduce the complexity of handling the command. In order to decouple the dependency resolution from the callers and also to scope components better based on duty state, app state, etc; we integrated

for dependency injection.

Every bit to consul the menstruation to other components rather than creating a burden on the caller, nosotros built few components as frameworks which invoke the caller functions appropriately or relied on events to trigger the flow. An example of this is the
Retry framework
which can be used past callers to retry a function unless successfully executed based on attributes like fourth dimension, strategies, retry attempts etc. Overall, applying this principle helped us create smaller reusable components at the same fourth dimension reduce the cumbersome problems involved while handling too many components.

High-Level Design

Based on our requirements and in a higher place principles nosotros laid out the blueprint of the App before writing any piece of code. Below diagram shows the loftier-level blueprint and major components involved.

Blueprint of the App

The Design patterns

Unidirectional Data Flow:

As nosotros have decided to build our sync modules, storage components in Native and UI in React native (based on above principles) we likewise need to stick to a blueprint in the way data should be flowing across these components. Taking inspiration from the Flux pattern and specially the mode REDUX works, we designed below design of the information flow(
server → storage → redux store → UI components

Pattern of the data menses across the components

Then, storage components in native acts as the unmarried source of truth (w.r.t the client) and redux shop in React native would be updated only afterward native storage components are updated from the server. So, any user interactions triggering data modification (ex: status update of an gild) would non be dispatched directly to the redux shop merely rather be passed on to the sync module in Native which makes asking to the server and appropriately update the storage components as-well-as publish the updates based on which redux shop would exist modified. This ensured usa avoid whatsoever inconsistency in information across components and the reliability of the data is persisted.

Pub-Sub Pattern:

For the most office, our application is
event driven
and honours a finite state machine for each delivery period. So, whenever any event or country transition occurs we might need to perform tasks like playing a audio and vibrating the telephone equally shortly as an social club is Assigned, showing a confirmation pop-up on the screen, uploading logs for real-time debugging, alerting partner when the battery level is disquisitional or in poor network expanse, etc. Below is an example showcasing the usage of this pattern in i of our core components.

An example showcasing the usage of pub-sub pattern in ane of our components

To simplify the reactive mechanisms mentioned above, we use


extensively across all components for publishing events to subscribers, streaming data, asynchronous and background execution of a task, buffering or throttling of events, periodic scheduling of a job, etc.

Scalability and Real-time Aspects

As we have decided upon the design principles and patterns to exist considered
(explained above), we besides had to have into consideration below explained aspects in detail before making the application live in the market.

Supporting offline/poor network weather

Since our partners spend near of their day travelling on the roads delivering orders with a smile, through tech solutions we wanted to make their workflow on the app a buttery-smooth experience past providing back up even in flaky/offline network conditions.
In oder to accomplish this, we made our
critical flows lighter
also as removed complex flows from the critical path,
built retry flows,
lazy sync mechanisms
and bcp modes(business continuity plan).

HLD for supporting offline/poor network scenarios

To make the above blueprint more robust and utilise the aforementioned ready beyond flows/apps,
we built our lazy sync module and retry framework as application agnostic
which takes a configuration of a role that is to perform, metadata such as max number of attempts/retry limit, duration of the timeout, policies(exponential, linear and fibonacci…), conditions and criteria etc.

Real-time Debugging

At Swiggy, we operate at a tremendous scale during which an issue affecting one delivery partner will bear upon
N orders/customers
where North can be any number equally we go along to grow at a rapid step (in bodily may be derived through parameters like need-supply ratio, growth rate, time of the day, duration of the outcome etc.). As our scale increases, our
Plough around Time
to identify the cause, length and breadth of an effect as well as finding the resolution
should subtract to minimise the touch on. For debugging issues on the mobile awarding, nosotros need to analyse data such as user interactions, control/data menses, network interactions (API calls made), application state, device data, user and zone level information etc. To a higher place
data that is to be nerveless should also be reported in existent fourth dimension
equally time ticking is of utmost importance during an issue. To solve this requirement,

we built a custom Logger solution

which can exist configured in real-time to study specific data of flow. Beneath is the loftier-level design of our solution.

HLD of Logger which records and reports real-time/historical logs collected

In a higher place solution helps us collect data whenever we are notified with an alert (by PagerDuty/NewRelic/Firebase Crashlytics), reported past mistake detection mechanisms baked in the app for critical flows or when an upshot is reported by the Operations squad from the ground. Based on the logs collected and real-time metrics (explained below) our team analyses the data quickly for faster resolution of the issue.

Real-time Health Monitoring

We operate 24×7 around the year, and then information technology is important to go on a constant heart and stay alert on the application health all the time. And so tracking metrics related to network, fatal/non-fatal errors, operational metrics each minute is crucial for our workflow. Below, we explained in-depth on how we constantly monitor each of these metrics.

Monitoring Network Metrics:

For tracking network metrics of all mobile applications across Swiggy, we’ve integrated

which helps in tracking info such as network error rates, traffic, response times for an API call and much more
insights existent-time

also as historic, provides us with
when any metric breaches the threshold, creating

custom dashboards

for a holistic picture of the application during any timeframe, etc. Beneath is one of the snapshots of our
real-time dashboard
which we created for our team to constantly keep an eye on / quickly refer during an ongoing issue.

Existent-time dashboard (in a higher place are a couple of snapshots only)

Monitoring Fatal/Non-Fatal Errors:

Firebase Crashlytics

helps in tracking fatal and non-fatal errors along with recording vital data such as device details, user identity. Information technology stitches firebase analytics information too on the same dashboard for each log making it easier to understand the user journey. Information technology fifty-fifty offers
real-time alerting based on velocity configuration
through multiple channels (nosotros configured Pager Duty and Slack for the same).

Realtime Monitoring and Debugging of the App


For whatever characteristic nosotros rollout, we plan to continue a config for turning it on/off, controlling the characteristic to only a subset of users based on sure properties like the city, zone, os versions, devices etc. Nothing best fits our requirement than the features provided by

Firebase Remote Config

which gives united states of america the flexibility to alter configs
real time
based on attributes such as user backdrop, device info etc.

Firebase remote config dashboard


As we handle one of the largest commitment fleets across Bharat and process millions of orders daily, it is super important to be stable. So, to mitigate any risk while adopting from older version to this awarding, we slowly and steadily rolled out this new awarding to the unabridged fleet making changes iteratively based on the inputs collected and in the process improving stability at each update. Every bit we are 100% alive to the entire armada,

today our application is stable for 99.ix% users
. We were able to attain this by sticking to our cadre principles, agreement the capabilities of React Native, real-time monitoring in place before GTM (get to market), setting upwardly fallback mechanisms, BCP(business concern continuity programme) modes during an issue and above all a Super-Duper squad handling our app.

Stability of our latest version of the App.


Overall, we talked about how we designed our new delivery application and addressed major technically challenging aspects. While some of these tech choices may look opinionated like React Native to Native distribution, It was indeed done to leveraging each framework’s cadre strengths and offerings. Working around each framework’s pain points helped us to go the nigh out of both worlds. At present, this also aligns with our core technology principles(The option criteria of any framework/tech should exist based on current and well-nigh-future concern needs and the customer base). I promise you got to learn a thing or two from this article.

Wait! we are non done nonetheless, Stay tuned for our adjacent commodity where nosotros volition talk about how nosotros are leveraging nearby and BLE beacons for indoor proximity detection.

I’m Narendra from Mobile team at Swiggy. If yous’re craving for innovation, bring together our squad before Thanos revives and snaps his finger once again.

We are hiring!