As a part of the menu markup project, we decoupled the concepts of a "Postmates" markup and a "Merchant" markup. Postmates markup is meant to be hidden to the merchant, and only visible to the buyers. Merchant markup is requested by the merchant, and should be visible in all apps (Buyer Frontend, Merchant Tablet, and Catalog Manager). The latter was something we did not previously support, until we introduced the merchant_price_increase
feature.
For this new merchant_price_increase
, applying a markup entailed actually mutating the catalog itself. This started with a ticket to backfill several thousands of places with the new mutated price, and then subsequently was followed up with features to support price mutations in God mode & the place bulk-updater tool.
The main reasons this approach was taken in the first place were:
- It was "simple." Once the price mutation happened, no other apps would have to think about this concept. The concept of merchant uplift was fully abstracted from all of our upstream clients (Postal Main, Catalog Manager, Merchant Tablet App).
- Latency concerns. If we stored the percentage in knapsack and calculated on the fly, we would have to join up to the root catalog of any item we were fetching, in order to acquire the percentage value.
However, several issues have arisen as this project has progressed:
- Keeping an entire Catalog in sync. If we edit the price of an individual product, that price has to take into account the
merchant_price_increase
. This complicates our code almost everywhere, and makes it less maintainable. - DB write load. Changing the
merchant_price_increase
of a Catalog effectively performs an entire re-ingest, without the ingest-benefits of queueing & managed demand.
As a solution to these problems, which are now evident to outweigh the benefits, we should explore rolling back this design and shifting to a "calculate on the fly" approach. This rollback will only happen on Catalog API, since new feature work is no longer being written (for the most part) for Knapsack V1. At the time of writing this, there are 1351 places on Catalog API with a merchant_price_increase
, and shifting to our new design can be fairly painless if we follow the right approach.
- Revert
merchant_price_icrease
to the "alternate" design for Catalog API only - Do so in a fashion that minimizes the time that the markup is incorrect to the buyer (e.g. it is applied twice or not applied at all)
- Update Knapsack logic to add the
catalog_id
as an argument to Catalog API queries. We will not use this argument in any way yet - Update Postal Main, Catalog Manager, and Merchant Tablet logic to pass in the
catalog_id
(i.e. thecore_place.uuid
) into every graphql fetch. Again, this argument will not be used for anything, yet. - Create a branch that includes the following logic:
- Prefetch the Catalog, using the provided
catalog_id
, in every graphql query - Add the
merchant_price_increase
of this Catalog to the Absinthe resolution context - Calculate the new price, including the merchant markup, inside of the resolver function. This is what we do today for the postmate's legacy markup.
- NOTE: This should live behind a feature flag if possible, instead of in a branch. Investigate using erlang variants
- Prefetch the Catalog, using the provided
- From BigQuery, generate a spreadsheet with a list of Catalog API places, along with the inverse of their current
merchant_price_increase
which would mutate their prices back down to their original price.
select
c.uuid, -1 * (100 * c.merchant_price_increase) / (100 + c.merchant_price_increase) as markup_inverse
from
`datafall-prod`.knapsack.catalogs c
where
c.merchant_price_increase is not null
and c.merchant_price_increase > 0;
- Create a script (similar to this one, but for Catalog API) that will mutate all catalog prices by the inverse percentage, but leave the value that was already in the
merchant_price_increase
column. With 1351 catalogs (most of which are fairly large Olo catalogs), I predict this script should take between 30 minutes and 1 hour.- This should happen in off-peak hours, while these stores are closed, as during this time the menu prices will be returned without a markup to buyer apps
- The BFE cache will need to be cleared ASAP after the script is run.
- After the script completes, enable the feature mentioned in Phase 1 Step 4