Case study 07 · Marketplace and revenue
Renewals and payment reminders handled by six daily jobs
The marketplace sold annual advertising, so several thousand customers renewed on different dates. Every day the jobs applied the same rules to each account.
6 jobs
the headline number
1 constraint
Every customer renewed on a different date, and nobody could watch several thousand expiry dates by hand.
The story in 5 steps
Stack
- AWS Lambda
- SQS
- MySQL
- Handlebars
- Node.js
01 · Context
On this platform, the revenue depended on six scheduled jobs that ran every day.
On this platform, the revenue depended on six scheduled jobs that ran every day. Scheduled jobs usually handle maintenance, such as cleanup, expiry and digests, but these handled renewals and payments.
Between them, the six jobs reminded advertisers before their listings expired, downgraded listings that fell too far behind on payment, processed recurring charges, chased unverified listings, ran a re-engagement campaign timed to the annual cycle and warned fleet operators about upcoming vehicle inspections.
02 · Could not change
The product sold annual advertising, so revenue came in on each customer's renewal date, and every customer had a different one.
The product sold annual advertising, so revenue came in on each customer's renewal date, and every customer had a different one. If that date passed unattended, the money did not come in at all.
Nobody could watch several thousand expiry dates by hand. The rule to downgrade a listing after non-payment also could not be left to someone's judgment, because a rule applied to some late accounts and skipped for others is worse than having no rule. It had to apply the same way to every account.
The commercial rules therefore had to be written in code and run on a schedule, without anyone deciding each day to run them.
03 · What I did
I made renewal the central job. It found listings approaching expiry and sent reminders.
I made renewal the central job. It found listings approaching expiry and sent reminders. When a listing was more than seven days late, the job downgraded it automatically, updated the invoice and re-indexed the record, so search showed the change immediately. Without the re-indexing, the downgrade would have existed only in the database, and the advertiser would have kept the placement they had stopped paying for.
Recurring payments had three outcomes. A successful charge, a failed charge and an upcoming charge each had their own message. I treated a failed payment as a reason to contact a customer who probably wanted to keep the service.
Re-engagement followed the annual cycle. A three-step campaign went out at roughly 179, 182 and 186 days after a listing's last update. About half a year before renewal, stale information in a listing is a sign that the owner has stopped thinking about it, and those owners are the ones who fail to renew.
I chose the channel for each job. Reminders about unfinished draft listings appeared in the app instead of arriving by email, so someone halfway through creating a listing found the reminder where they had left off.
All mail went through one sending service. Every job followed the same steps: query the database, take a template from object storage, write a record and put a message on a queue. Outside production, that service redirected all mail to a test address, so there was no way for staging to email a real customer.
04 · Result
Six daily jobs that ran renewal, downgrade, dunning and re-engagement
- Six daily jobs that ran renewal, downgrade, dunning and re-engagement
- The same commercial rules applied to every account, without anyone having to decide to apply them
- 55 email templates, all going out through a single sending service
05 · Differently
The jobs ran daily and reported only their errors.
The jobs ran daily and reported only their errors. There was no way to see how many listings had been downgraded in a given week, or whether the re-engagement campaign changed anything at all. I would add a business-level report next to the error log that answers those two questions. Without it, a job that stopped working would only have come to light when someone asked why revenue dipped.
Related services
The services that draw on this work.
- Regulated and sensitive systemsFintech developmentSix daily jobs that handle renewals, downgrades, dunning and reminders for a US marketplace.
- Web developmentMarketplace and logistics platformsSix daily jobs handle renewal, downgrades, dunning and re-engagement for the marketplace’s annual advertising, and apply the same rules to every account.
- Web developmentSEO and programmatic pagesWhen a listing is downgraded for non-payment, it is re-indexed straight away, so search results match what the advertiser pays for.
- Web developmentAdmin dashboards and internal toolsSix jobs that run on their own every day to handle renewals, downgrades, recurring charges and re-engagement. Their emails come from 55 templates and go out through one sending service.
- Backend, data and integrationsPayment integrationsRecurring charges for a marketplace’s advertisers through Stripe, PayPal, Apple Pay and Google Pay. A successful charge, a failed one and an upcoming one each send the customer a different message.
- Backend, data and integrationsScheduled jobs and billing logicSix daily jobs on a US marketplace for truck services. They sent reminders before expiry, downgraded listings after non-payment, processed recurring charges, followed up on unverified listings, ran a re-engagement campaign and warned fleet operators about upcoming vehicle inspections.
- Backend, data and integrationsEmail infrastructureRenewals, payment notices and re-engagement on a US marketplace went out from 55 email templates through a single sending service.
- Regulated and sensitive systemsInvoicing and customs systemsOn a US marketplace, the daily renewal job downgrades a listing more than seven days late, updates its invoice and re-indexes the record, by the same rule for every account.
Case study 07
Working on a similar problem? We reply within one business day.
The first call takes 30 minutes, and you’re under no obligation.