← All technical work

Off-Premises Dining Platform · Last Mile Delivery

Multi-Provider Delivery Orchestration

A provider-independent architecture for integrating third-party delivery into restaurant fulfillment

Architected a reusable delivery capability that allowed Restaurant Operations to request third-party drivers without knowing how individual providers worked. Standardized contracts abstracted provider-specific APIs and workflows, while restaurant-level configuration controlled provider preference and fallback. Provider callbacks were normalized and routed through the enterprise messaging architecture to keep restaurant teams informed as deliveries changed.

Scalable capacity
Third-party drivers on demand
Flexible sourcing
Third-party or restaurant delivery
Multi-provider
Provider-independent architecture

Problem & Constraints

As off-premises dining grew, the company wanted to shift more delivery fulfillment from restaurant employees to third-party delivery providers while continuing to own the guest ordering experience. The technical challenge was not simply integrating a delivery provider. Each provider exposed different APIs, contracts, workflows, coverage, and operating constraints, while Restaurant Operations needed a consistent way to request and manage delivery regardless of which provider ultimately fulfilled the order. The architecture also had to accommodate brand and restaurant-level provider preferences, handle provider unavailability, and return delivery lifecycle changes to the restaurant without coupling the restaurant platform to individual providers.

Provider variability
Different APIs, contracts, workflows, and reservation requirements across delivery providers
Business policy
Brand and restaurant-level rules governing provider eligibility, preference, and priority
Fulfillment resilience
Ordered fallback when the preferred provider was unavailable or unable to reserve a driver
Lifecycle coordination
Provider status changes and driver updates routed back to the appropriate restaurant and order

Architecture Overview

Architecture showing Last-Mile Delivery orchestrating multiple delivery providers through standardized APIs, configurable provider selection, and enterprise messaging
Provider-independent architecture for multi-provider delivery orchestration

Last-Mile Delivery was designed as a provider-independent layer between Restaurant Operations and external delivery services. Restaurant systems interacted with a standardized API rather than provider-specific integrations, while the platform selected providers according to restaurant configuration and translated common delivery requests into the APIs, contracts, and multi-step workflows required by each provider. Ordered fallback allowed another eligible provider to be attempted when the preferred provider could not reserve a driver. The architecture also managed the return path as deliveries progressed. Provider webhooks entered through Azure API Management and were processed by Azure Functions, where updates could be validated, normalized, and correlated to the appropriate delivery. The platform then used the existing enterprise event-driven architecture, including Event Grid and Service Bus, to route delivery and driver updates back to the appropriate restaurant without exposing Restaurant Operations to provider-specific lifecycle behavior.

Key Architecture Decisions

Abstract providers behind a common delivery capability

Give Restaurant Operations a stable API for requesting and managing third-party delivery rather than exposing individual provider contracts and workflows. A facade kept provider complexity behind the service boundary and allowed the restaurant platform to remain independent of any specific delivery provider.

Isolate provider-specific behavior

Encapsulate each provider’s APIs, contracts, and multi-step reservation workflow behind its own implementation. Strategy and Adapter patterns allowed the platform to select the appropriate provider at runtime while translating standardized delivery requests and responses to and from provider-specific models.

Make provider selection configuration-driven

Keep provider eligibility and preference in restaurant configuration rather than application code. Active providers and their priority could vary by restaurant or brand, allowing business agreements, geographic coverage, and operating needs to change without restructuring the integration architecture.

Build fallback into the orchestration layer

Treat provider unavailability as an expected operating condition rather than an integration failure. When the preferred provider could not reserve a driver, the orchestration layer could move through the configured sequence of eligible providers without requiring Restaurant Operations to understand or manage the fallback process.

Separate external callbacks from internal messaging

Route provider webhooks through a controlled API boundary rather than exposing internal messaging infrastructure. Azure API Management and HTTP-triggered Functions provided the ingress path for validating, normalizing, and correlating provider updates before they entered the enterprise event and messaging architecture.

Reuse enterprise messaging for the return path

Use the existing enterprise event-driven architecture to deliver lifecycle changes back to the appropriate restaurant. Event Grid handled events while Service Bus carried business messages, allowing Last-Mile Delivery to participate in established enterprise-to-restaurant messaging rather than creating a separate delivery-specific channel.

Engineering Approach

The engineering approach focused on keeping external provider complexity isolated from the rest of the OPD platform. Restaurant Operations understood the delivery capability and its standardized contracts, but not the provider-specific APIs, workflows, or selection logic behind them. Provider-specific implementations, configuration-driven behavior, and controlled integration boundaries allowed delivery providers to vary independently while preserving a consistent operating model for the restaurant.

Application & Services
.NET · RESTful APIs · Azure Service Fabric · Azure API Management · Azure Functions
Data & Integration
Azure Service Bus · Azure Event Grid · HTTP Webhooks · Asynchronous Messaging · Provider APIs
Patterns & Principles
Facade · Strategy · Adapter · Workflow Orchestration · SOLID Principles · Separation of Concerns
Release & Reliability
Configurable Timeouts · Ordered Provider Fallback · Operational Re-request · Delivery State Correlation · Lifecycle Event Processing
Security
Controlled API Ingress · Protected Internal Messaging · API Boundary Isolation

Results & Evolution

What began with the integration of a single third-party delivery provider became a reusable delivery capability within the broader OPD platform. Because Restaurant Operations depended on standardized delivery contracts rather than provider-specific implementations, additional providers and changing fulfillment rules could be introduced behind the same operating model without restructuring the restaurant application.

  • Expanded beyond the first provider: The initial implementation supported DoorDash Drive, but the architecture was designed for multiple providers from the beginning. Additional providers could be introduced through their own implementations while preserving the standardized interface used by Restaurant Operations.
  • Turned provider choice into business policy: Provider availability and preference could be configured by restaurant, allowing the platform to accommodate brand agreements, geographic coverage, and local operating differences without hardcoding those decisions into the restaurant application.
  • Added resilience across providers: When the preferred provider was unavailable or unable to reserve a driver, the platform could move through the configured sequence of eligible providers rather than treating the first failed attempt as the end of the fulfillment process.
  • Preserved operational flexibility: Restaurant teams retained the ability to request a third-party driver during the eligible order lifecycle, retry after an unsuccessful attempt, or continue with native delivery when appropriate. Automation supported the operation without removing restaurant-level control.
  • Extended delivery management beyond reservation: Provider callbacks brought driver and delivery changes back into OPD after the initial reservation. Updates could be correlated to the active delivery and routed to the appropriate restaurant, allowing the fulfillment experience to remain connected as provider-side conditions changed.

Architectural Perspective

One of the lessons this architecture reinforced for me is that a good abstraction starts with understanding what should remain stable and what is likely to change. Restaurant Operations did not need to understand DoorDash, Uber, or the mechanics of any other delivery provider. It needed a consistent way to request delivery and understand the outcome. That boundary allowed the variability to remain where it belonged. Provider-specific contracts and workflows could change behind the interface, configuration could express which providers the business wanted to use and in what order, and the orchestration layer could manage those differences without pushing them into the restaurant platform. The goal of abstraction is not simply to hide complexity. It is to put complexity in the part of the architecture best equipped to absorb change.