Designing a Recurring Order/Payment Engine for an eCommerce Platform (e.g. Shopify, BigCommerce)

During my recent job search for a role in product management, I was interviewing with Acme Corporation to join their e-commerce team.

After the HR screening and a preliminary interview with one of their mid-level PMs, I was invited to the 2nd round with the head of product, Jennifer. We had a pretty enjoyable “shop” talk and agreed that I should take the homework assignment: I am to formulate an initial description for a portion of a new capability within Acme’s platform. Its high-level purpose is to enable shoppers to submit orders for recurring deliveries — think of a monthly “dose” of toilet paper delivered to your doorstep. “Specifically”, was expected to use my imagination and free will to describe any component I wished, since Acme was hiring PMs for the user interface and well as back-end processing.

Earlier in my career, I’ve done work in supply-chain planning followed by doing programming in Java on AWS. Therefore I decided to imagine a set of use cases/scenarios that such an engine might be able to deliver which would be implemented on the backend.

Case 1: “Monthiversary”

The most straightforward outcome of merchant configuration and user action is the following sequence:

  1. Shopper submits their subscription on January 6th;
  2. Acme Corp. processes the initial order on January 6th;
  3. Each next 6th day of the month (e.g., Feb-6, March-6, Apr-6, etc.) Acme Corp. processes another recurring order for this shopper.
  • In case when the monthiversary of the initial order falls on a day of the month that does not “exist” (e.g., Jan31-to-Feb31) the recurring order processing date is set to the last day of the month (e.g., Feb28/29)

Case 2 += “Skip-is-ON/OFF”

Since a shopper may wish to skip a specific recurring order/shipment, they can “mark” a toggle to skip the next (recurring) order. In such a case, the expansion of the previous scenario continues like this:

3. Each next 6th day of the month, Acme Corp. checks the skip:

If skip-is-ON: do NOT process an order; flip to skip-is-OFF;

Else: process order;

Case 3 += “BatchDayOfMonth”

Some merchants may wish to optimize their fulfillment/operations by batching all recurring orders within the month, on a specific day of the month, instead of spreading them over the monthiversary for each shopper. This configuration is optional and can be set for the entire “catalog” or each product. The value for BatchDayOfMonth is given as an integer such as 15: meaning the 15th day of each month; or 31: indicating the 31st day of each month like Jan 31th BUT not Feb 31st — if a month does not “have” such a day, the setting is automatically converted (for that interval) into the last day of that month, therefore, Feb 28/29th depending on the leap year. Thus, the expanded sequence looks like this:

0. Merchant sets the BatchDayOfMonth to 15;

  1. Shopper submits their subscription on January 6th;
  2. Acme Corp. processes the initial order on January 6th;
  3. Each next 15th day of the month (e.g., Jan 15th), Acme Corp. checks the skip:
  4. If skip-is-ON: do NOT process an order; flip to skip-is-OFF; Therefore, this user would get one order on Jan6 and (possibly) another on Feb15;
  5. Else: process order; Resulting in one order on Jan6 and another order again “today” on Jan15, then (possibly) Feb15, etc.
  • A special case is when the initial order is submitted on the day of the BatchDayOfTheMonth in which case the initial order also acts as de facto the 1st recurring order for this shopper.

Case 4 += “CutoffDayForFirstBatchEligibility”

When BatchDayOfTheMonth is in effect there is some chance that the shopper might get surprised by the 2nd order they receive (the 1st recurring shipment) as it might occur in very short proximity to their initial order/receipt. For InitialOrderSubmissionDay=14 and with the BatchDayOfTheMonth=15 the shopper might get shipments on consecutive days whereas they were mainly expecting something more similar to about-once-per-month. Of course, they might actually want this to happen (more sales are great; the user might want to build up their “buffer” at home or gift to their friends, etc); OR the shopper could act quickly and set the skip-is-ON. To reduce the chance of unwanted shipment (& unwanted billing cost to the shopper), the merchant can choose to utilize an optional configuration CutoffDayForFirstBatchEligibility. If the initial order happens before the cutoff day (during the current batch interval) the shopper is eligible for the recurring order (which the user can skip by setting the skip-is-ON). Otherwise, the user is not eligible for the upcoming batch date and they would instead have the option to receive or skip the batch day order happening in ~32+ days ahead:

0. Merchant sets the BatchDayOfMonth to 15; And they also can/do set the CutoffDayForFirstBatchEligibility to 12;

  1. Shopper submits their subscription on January 6th;
  2. Acme Corp. processes the initial order on January 6th;
  3. On Jan15 the user is eligible for the batch order because the initial submission was 6, which is on-or-before 12; Acme Corp. checks the skip:
  4. If skip-is-ON: do NOT process an order; flip to skip-is-OFF; Therefore, this user would get one order on Jan6 and (possibly) another on Feb15;
  5. Else: process order; Resulting in one order on Jan6 and another order again “today” on Jan15, then (possibly) Feb15, etc.
  • If the CutOffDay… were set to 5, this user would not have been eligible for the Jan15 batch and their choice would have been to accept/skip the Feb15 batch order.

We can think of the cutoff as splitting a batch interval into two parts — “eligible” & “not-eligible”. Consider these settings and computations:

When BatchDayOfTheMonth=15 && CutoffDayForFirstBatchEligibility=6;

  • Feb15 batch interval is Jan16 to Feb15
  • Initial customers are eligible for Feb15 if their order is first submitted within Jan16-Feb6
  • or NOT eligible for Feb15 if their order is first submitted within Feb7 and Feb14

…BatchDayOfTheMonth=10 && CutoffDayForFirstBatchEligibility=20;

  • Jan10 batch interval is Dec11-Jan10
  • Initial customers are eligible for Jan10 if their order is submitted within Dec11-Dec20
  • or NOT eligible for Jan10 if their order is submitted within Dec21-Jan9.

Therefore it is important to note when the CutoffDayForFirstBatchEligibility value is greater in an absolute sense than the value of BatchDayOfTheMonth: the cutoff happens during the calendar month previous to the given batch calendar date (actual) — e.g., Jan10 batch vs. its Dec20 cutoff; as opposed to Jan15 batch vs. Jan6 cutoff.

I maintain RemixRotation and AlgosForCryptos publications…

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store