Every delivery enabled by the DoorDash platform is different. Dashers (our term for delivery drivers) meet customers in a wide range of contexts, from apartment and office building lobbies to suburban homes. This variety of circumstances and the timely nature of contact makes communication essential, which is why we built chat into the DoorDash apps.

Building chat into our apps may seem redundant, as smartphones already support calling and texting. However, building our own chat client has several advantages over these external channels. Our chat client creates a buffer between Dashers and customers, ensuring privacy for both parties, and lets us better resolve customer support issues.

Creating a chat client requires quite a bit of engineering and, given our past success integrating existing solutions, we began this project by evaluating third-party software. After settling on a chat technology, we integrated it into our platform and apps.

Relying on a third party solution contributed to a rapid development time for this project. The resulting communication channel has led to an overall better experience for Dashers and consumers.

The problem with external communication channels

Before we implemented in-app chat, a Dasher attempting a delivery might try to call or text the customer if finding the location proved difficult or other issues arose. Although this method may be effective, it requires the Dasher to switch away from the app, which shows the delivery address and other important details.

Communication through such external channels cannot be reviewed by our customer obsession team. If there were a misunderstanding between a Dasher and a customer, our agents would have little context to help resolve the issue. The ability to see communication between the two parties, along with other delivery data such as order, pick-up, and drop-off times, helps our agents arrive at satisfactory solutions for all concerned.

Evaluating chat options

As with any significant new feature, we first needed to consider whether to build it or use existing technology. Chat is almost as old as the Internet, and there are many products enabling it. Seeing no need to reinvent the wheel, we determined our requirements and then evaluated which existing technologies could give us those capabilities and integrate with our platform. 

The critical features for chat in the DoorDash apps included:

  • Push notifications
  • Chat history and timestamps
  • Read receipts
  • Customizable user interface kit (UIKit)
  • Voice over IP (VoIP)

Push notifications ensure that Dashers and customers know they’ve received a message. Both the chat history and read receipts help our customer service agents review interactions and solve issues. The user interface kit lets us integrate the chat interface into our apps while preserving the DoorDash look and feel. VoIP adds the capability for voice chats, which can, at times, be more effective than text chat. A few secondary requirements included content moderation, high quality documentation, and the ability to integrate chatbots.

Our survey of chat technologies resulted in a shortlist comprised of SendBird, Twilio, and Pubnub.

We evaluated each option thoroughly and decided to go with SendBird. Twilio got excluded from our analysis almost immediately because it does not provide a customizable UIKit and lacks some of the features that SendBird and Pubnub provide. Comparing SendBird and Pubnub, we finally decided to go with SendBird because of its easy-to-use chat API and a fully-managed chat platform on the backend. It also provides elegant pre-built UI components. 

Integrating SendBird

Our system design consists of four main components: mobile clients, chat service, data store, and SendBird SDKs. The in-app chat entry points have been added to all of DoorDash’s mobile clients. Mobile clients connect to the chat service to get the chat user and chat channels. The chat service handles communications between the data store and SendBird platform APIs. In the data store we maintain users and channels that get created by SendBird. The chat service uses SendBird to create users, chat channels, and channel metadata, and then stores that data.

Our in-app chat system design consists of four main components: mobile clients, chat service, data store, and SendBird SDKs. The chat service receives chat user and channel requests from the mobile clients, sending them to the SendBird platform. SendBird creates channels and users and updates the message status. The chat service also stores the chats in a Redis data store.
Figure 1: Our in-app chat system design consists of four main components: mobile clients, chat service, data store, and SendBird SDKs. The chat service receives chat user and channel requests from the mobile clients, sending them to the SendBird platform. SendBird creates channels and users and updates the message status. The chat service also stores the chats in a Redis data store.

Connecting the mobile apps

On the mobile side we built a framework that serves as a wrapper around the SendBird UI SDK. The framework adds UI styling and configuration on top of the chat SDK UI. The framework is integrated in both consumer and Dasher mobile apps. Building the framework helped us to isolate the chat-related logic and maintain it in one place.

Integrating chat into our mobile apps required work on four separate codebases. We have the consumer and Dasher apps, with Android and iOS versions of each. 

Both applications, consumer and Dasher, share the same chat window UI and logic. To avoid duplicating the same implementation in all of our apps, we decided to build a framework, one for iOS and another for Android. Each framework is integrated in the consumer and Dasher apps. 

The SendBird SDKs are integrated into the framework, and the framework mostly serves as a wrapper around the SendBird SDKs, as shown in Figure 2, below. The framework APIs:

  • Create the chat and inbox UI and return to the client 
  • Initialize the SendBird SDKs
  • Register a device token for the SendBird push notifications
  • Create the chat button and manage its state
The framework is essentially a wrapper around the SendBird SDKs, which we can integrate with our mobile apps to enable chat.
Figure 2: The framework is essentially a wrapper around the SendBird SDKs, which we can integrate with our mobile apps to enable chat.

On the Dasher side, the chat button appears on the delivery screens so Dashers can initiate the chat with consumers about orders while they are on a delivery. We added the inbox button to the home screen and to the timeline screen, making it easy for Dashers to find new messages. Tapping the inbox button lets a Dasher view all their messages in one place, as shown in Figure 3, below:

The inbox screen, created through the SendBird SDK, makes it convenient to view all customer messages at the same time.
Figure 3: The inbox screen, created through the SendBird SDK, makes it convenient to view all customer messages at the same time.

On the consumer side, the chat button is added to the order card. Consumers can initiate a chat with their Dasher after they place an order.

Exploring the chat service

The chat service is an independent deployable service. The chat service maintains the active channel status and creates users. 

Creating users

Consumers engaging in an order transaction become eligible for in-app chat. At app launch the clients ask the chat service to create a new user on the SendBird platform. Once the chat service is notified that the user has been successfully created, it stores the user information in the data store.

Creating and updating chat channels

Because chat only becomes available during an order and delivery transaction, the chat service needs to listen for specific delivery events. Events that will initiate or cancel a chat are:

  • Order is placed
  • Order is unassigned/reassigned
  • Dasher accepts an order
  • Delivery is canceled 
  • Order is delivered

When a consumer places an order and a Dasher accepts the delivery, a Dasher accepted order event is sent to the chat service. The chat service tells SendBird to create a chat channel. Once the chat service is notified that the chat channel has been successfully created on the SendBird platform, the chat service updates the channel status in the data store.

Configuring the data store

Because chat sessions are temporary events, we chose Redis as our data store, using it as a cache layer for the user info and chat channel status. Redis was also an easy choice, as it is already available in our cloud infrastructure. 

SendBird stores the actual chat text on its platform, which is SOC 2 certified and GDPR compliant, ensuring security and privacy. A pipeline between SendBird and our customer service system lets authorized users view chat histories to help resolve support issues.

Integrating SendBird SDKs

As a hosted service, SendBird maintains its own platform, letting our engineers focus on our logistics platform and customer experience. We only had to integrate SendBird into our platform through the chat API provided in the company’s SDKs.

Using the SendBird API, we were able to customize our chat experience at a very granular level. For example, when a Dasher drops off an order, our chat services, using the SendBird API, can ask the SendBird systems to send an admin message to the customer that the food has been dropped off. 

Results

Adding in-app chat to our consumer and Dasher apps decreased the number of orders showing as Never Delivered, a metric we use to measure how many deliveries were missed. One of the most common causes of Never Delivered is poor communication between a consumer and Dasher. 

Prior to in-app chat, both parties could communicate only via text and phone. These two options are not the most reliable communication options since they can fail due to wrong phone numbers specified in the account profile. Because in-app chat doesn’t rely on phone numbers, and users don’t have to leave the app when they want to chat, we were able to decrease the Never Delivered rate and prove in-app chat’s success. 

Conclusion

SendBird let us build an efficient solution in a short period of time with fewer engineering resources than if we tried to build our own chat solution. Ultimately, it proved one of our guiding principles: choosing the most pragmatic solution for the task.

Whether it’s chat or some other feature, technology companies should carefully consider whether to incorporate a third-party library or build something in-house. In our case, chat was not a core competency on our team, and we wanted to focus our resources on improving our logistics platform. The number of chat solutions available gave us plenty of options to consider.

As shown by our metrics, chat is very important for our customer experience, which could suggest a need to own the underlying technology. However, a process of setting clear expectations for what’s needed at the beginning of the project, and engaging in a thorough evaluation of options, mitigated any risk of outsourcing this particular feature.

Header photo by Malcolm Lightbody on Unsplash.