Can We Duplicate the Database?

When one API server could not handle enough requests, we ran several instances behind a load balancer. That let us handle more traffic. (It also provided redundancy: the system continued to work even if one instance went down.) Could we do the same thing with the database?

Suppose we copy Shopend’s database onto a second server. Both servers now hold every shop’s products, carts, and orders. We send some requests to one and some to the other. If each server handles half the work, it looks as though we have more capacity.

Replication

Maintaining copies of data on multiple database servers is called replication. Each copy is a replica. We can have more than two. Here is the design with three replicas and a load balancer in front of them:

graph TB
    A[Shopend API Instances] -->|Database requests| LB[Database Load Balancer]
    LB --> R1[(Replica A)]
    LB --> R2[(Replica B)]
    LB --> R3[(Replica C)]

The load balancer distributes the database requests across the replicas.

Reading from a different replica

There is a difference between the API instances and the replicas. The API instances all read and change the same stored data. When one instance records an order, the next request finds that order, whichever instance handles it. Each replica stores its own copy of the data.

Suppose a shopper places order 92, and the load balancer sends the request to replica A. Replica A records the order, and the purchase succeeds. The shopper then opens order 92. This time the load balancer sends the request to replica B.

Request Routed to Result
Shopper places order 92 Replica A Order 92 is recorded; the purchase succeeds
Shopper opens order 92 Replica B Order not found

Order 92 exists on replica A. Recording it there did not change replica B.

Keeping the replicas updated

A change recorded on one replica must be passed to the others. Here, replica A sends the purchase’s changes to replicas B and C:

graph LR
    A[(Replica A)] -->|Purchase changes| B[(Replica B)]
    A -->|Purchase changes| C[(Replica C)]

Once replica B applies those changes, it can return order 92. Until then, a read from replica B will fail to find this order.

Unlike duplicated API instances, database replicas must be kept in sync as the data changes. Every change recorded on one replica must be passed to the others so that they continue to hold the same data.