Checkout-path caching: catalog, inventory deltas and customer state
The path to checkout reads three kinds of data with three different freshness needs. Here is how a memory cache kept in step with the database handles each, and where the limits are.
An online store's checkout is a sequence of reads that ends in one write. Along the way the application asks for the product catalog, the current stock position and the state of the customer's own session. Each of the three changes at a different rate, and treating them as one problem is how most caches end up either stale or useless.
Three kinds of data, three rates of change
The catalog is the slow one. Product names, descriptions, images and list prices change when a merchandiser edits them, which for most rows is rarely and for the whole catalog is a steady trickle. It is also the most read: every product page, search result and basket line pulls from it.
Inventory is the fast one, and it changes in small deltas (a delta is the difference between the old value and the new one, here a stock count going down by one or up by a pallet). Every order, every return, every warehouse receipt moves a number. The absolute count matters less than the direction; the question the page asks is whether the item can still be bought.
Customer state is per session. The basket, the chosen delivery address, the saved payment method and the loyalty balance belong to one person and change while that person is active. It is read many times in one session and then goes quiet for weeks.
How a synced cache treats each
redfly keeps a copy of the tables the application reads in Redis (a memory store that answers in about a millisecond) and serves reads from there. A sync service watches the database for changes: on SQL Server it reads change tracking on a short interval, and on PostgreSQL and MongoDB it streams changes through logical replication and change streams. Changed rows land in Redis shortly after. The application calls Get, GetRows or GetTotalRowCount and never sees which store answered.
For the catalog, that means the product page is a memory read, and a price edit shows up shortly after the merchandiser saves it. There is no expiry timer to tune, because the copy is refreshed by the change, not by the clock.
For inventory, each stock movement is a row change like any other. The sync service carries the new value to Redis, and the product page shows it on the next read. The cache never tries to apply deltas itself; the database is where the arithmetic happens, and the cache reflects the result.
For customer state, the basket row and the address row are synced the same way. A shopper who adds an item writes to the database; the change reaches Redis a moment later; the next page load reads it from memory.
The cache does not decide what is fresh; the database's own list of changes does.
Writes go straight to the database
Placing the order is the one write on the path, and it does not touch the cache on the way in. The application calls Insert, the row lands in the database, and the same change signal that carries every other row carries the order out to Redis afterwards. The order is committed with the database's usual guarantees, and the stock reduction that goes with it is a database transaction (a set of changes applied together or not at all), not a cache operation.
This is the part that makes the design safe for money. Nothing that decides whether a sale happened depends on memory. Memory only decides how quickly the shopper sees the pages around the sale.
The honest limits
The copy in Redis lags the database by a little, so a stock count on a product page can be a moment old. For a page that is fine. For the moment of purchase it is not, and the application should treat the final stock check as part of the order write, which is what the Insert already is. A store that shows three left and sells four in the same second has a problem no cache solves; the database transaction on the order is what refuses the fourth.
Session data that never reaches the database, such as a basket held only in browser storage, is outside the sync and stays outside it. If Redis is unreachable, reads fall back to the database automatically; the checkout keeps working, more slowly, until the cache is back.
The tables to cache also have to be chosen and the memory sized for them. A catalog of a million rows with images stored as text is a different sizing conversation from a catalog of ten thousand rows with image links.
What this removes from the codebase
No cache keys, no expiry settings, no invalidation calls after writes, no logic that decides which of three stores holds the truth. The application reads through one API and writes through the same API, over REST or gRPC (two standard ways for programs to call a service over a network). The freshness rules for catalog, inventory and customer state are all the same rule, because the sync treats every row alike.
That also removes a class of bug. The hand-built version of this design usually has three caches with three expiry policies, and the failure is a basket that shows an old price next to a stock count that is newer than the order. One sync, one lag, one rule.
Where redfly fits
redfly is the API and the sync service in this picture, deployed in the retailer's own cloud account or on their own servers, working with them as a design partner. The store, the checkout and the database stay theirs.