Taxi Service

March 09, 2023 | Glynn Bird | Replication PouchDB

We’ve all used taxi or ride-sharing services where the customer uses a mobile app to define the start and end point of their journey, then a driver chooses the job and makes their way to the start point. Such applications are complex distributed, real-time systems with data originating from:

These actors are expecting that data can be shared between them from disconnected databases over potentially flaky mobile connections.

taxi driver

Photo by Waldemar on Unsplash

Cloudant seems like a good fit for this application because:

In this blog post we’ll see how such a system could be designed with Cloudant and PouchDB to give the best scalability and to avoid some replication pitfalls.

Cloudant replication 🔗

Cloudant replication is mostly used to copy data from one Cloudant database to another, typically another Cloudant service in a different IBM Cloud region. As Cloudant replication uses the same protocol as its open-source sibling Apache CouchDB, it can also be used to transfer data between PouchDB or CouchDB and Cloudant. PouchDB can be be embedded into mobile apps to:

It seems like replication is going to be a powerful tool in transferring data between mobile and cloud replicas, in both directions. But before we get carried away we have some design decisions to make.

Data design 🔗

We will likely have a database containing the taxi drivers that are on the company’s books and the customers that have signed up to use the app. One document per driver/user would make sense here as this data need not be updated frequently. This data can stay on the cloud-side Cloudant databases and needn’t be replicated to the driver or customer’s devices.

As for the journey data, it’s tempting to go for a “one document per journey” schema. The document could start small with just the customer’s location and destination. At a later date the nominated driver details could be added. The document would be modified over its life as the journey proceeds, adding driver location over time, billing information and journey status.

There are some drawbacks to consider with this approach:

Perhaps there’s a data design other than “one document per journey” that overcomes these pitfalls?

A possible solution 🔗

There is a solution which allows for:

The solution is to create one database per live journey, where the database contains write only documents, each representing an event throughout the lifecycle of the trip e.g.

Note: documents types marked * could appear multiple times in the database.

A per-journey database can be created as soon as the customer has supplied their location, destination and trip parameters e.g. “wheelchair access required”. The database starts off small and slowly gains documents over the lifetime of the trip. Importantly, no document is ever edited or deleted so there is no possibility of document conflicts. This avoids having to deal with building a complex “conflict resolution” algorithm.

API keys granting both customer and driver access to the server-side data can be generated when the database is created. When the trip is complete, the API keys can be revoked.

taxi diagram

Each party would have a copy of the data (the driver and customer in PouchDB, and Cloudant with a copy in the cloud). The client-side applications would have to fetch all of the documents in their local database to find out the current status of the trip and its entire history. Continuous replications between mobile and cloud replicas would keep each database in sync and the mobile device would be notified as new documents arrive from elsewhere.

Once the trip is complete, the individual event documents could be combined into a single summary document which can be stored in a separate reporting database (or collection of timeboxed reporting databases) on the server-side. The original per-trip database can then be deleted, as we don’t want thousands of Cloudant databases lying around forever.

Conclusion 🔗

It is tempting to use Cloudant’s replication in conjuction with PouchDB for mobile applications but careful planning must be undertaken to avoid creating an unscalable or unmanagable solution. The key design aims are: