Running peak season off the warehouse
Warehouse-native CRM holds up under peak load if you plan for the failure modes: sync latency, rate limits, stale audiences and what sends when the list arrives late.
It is seven in the morning on the biggest trading day of the year. The audience for the eight o'clock send is built by a model in the warehouse, pushed to the engagement platform by a sync, and it has not arrived. The campaign is scheduled, the creative is approved, and the list is empty.
By twenty past seven somebody is asking whether to send to last week's saved audience instead. That is the decision peak season actually turns on, and it is much easier to make if you made it in October.
Running lifecycle marketing off the data warehouse is settled practice now. The modelling is not the risky part. The risky part is the two hundred metres between a correct table and a message in an inbox, under load, on the one day volumes are four times normal.
What breaks under load is the transport, not the model
A composable CDP splits the job in two. The warehouse holds the customer record and the logic; reverse ETL moves the results into the tools that send. In normal weeks the split is invisible, because everything completes long before anyone looks.
Peak compresses the timetable. The overnight ELT run takes longer because yesterday had four times the orders. The audience model waits on that run. The sync waits on the model. Each step is a little slower, and the delays add up at the far end of the chain.
The result is the twenty-minute late audience. Nothing failed. Every job returned success. The list simply landed after the send window opened, which for the customer is indistinguishable from a broken campaign.
So the first piece of peak planning is not a new model. It is a timing diagram: every job in the chain, its normal duration, its worst observed duration, and the time the first send needs it.
Treat rate limits as a budget you allocate
Every engagement platform limits how fast you can write to it. On a normal Tuesday nobody notices. During peak you are pushing large audiences, high-frequency behavioural updates and profile changes through the same allowance, and the allowance does not grow because it is November.
Find the real numbers before the season. Ask the vendor for the documented limits on the endpoints you use, then measure what you actually consume on a busy day. The gap between those two figures is your headroom, and it is usually smaller than people assume.
Then spend it deliberately:
- Rank the syncs. Audience membership for a scheduled send beats a nightly attribute refresh, every time.
- Push changes, not full tables. A daily full-profile resync during peak is the most common self-inflicted throttle.
- Move slow-changing attributes to a weekly schedule for the duration, and say so in writing.
- Separate the pipeline that feeds triggered journeys from the one that feeds broadcasts, so a broadcast build cannot delay a basket abandonment.
- Put a hard cap on retries, because an aggressive retry loop against a throttled endpoint extends the outage it is responding to.
Watch queue depth rather than job status. A sync that is running and falling behind reports as healthy, and the number that shows the truth is how many rows are waiting.
Give every audience a freshness contract
Not every audience needs to be current to the minute, and pretending otherwise is what overloads the pipeline. Write down, per audience, how stale it is allowed to be before it must not be used.
Three tiers cover most programmes. Real time, for anything triggered by a session in progress. Hourly, for basket and browse activity that still has commercial value later in the day. Daily, for segment definitions built on purchase history, loyalty tier or propensity scores.
Write the tier into the audience definition itself, with a last-refreshed timestamp attached to every row. The send should be able to read that timestamp and act on it without a human in the loop.
This is also where the modelling layer earns its keep. Scores and derived attributes computed in the lakehouse can be materialised once and reused by a dozen audiences, instead of each audience recomputing the same joins under time pressure.
Decide now what sends when the audience is late
Every peak has at least one late audience. The question is only whether the response was designed or improvised.
Give every scheduled peak send a written fallback. Agree it in advance with whoever owns the commercial number:
- Send to the last successfully synced version of the audience, if it is within its freshness tier.
- Send to a broader, pre-built audience, accepting lower relevance to keep the slot.
- Delay by a fixed interval, once, then re-evaluate at a stated time.
- Cancel, and do not attempt to recover the send later in the day.
Attach the choice to the campaign brief, not to a runbook nobody opens. The person who has to act at seven twenty in the morning should read it in the same place they read the subject line.
Option four deserves more use than it gets. A recovered send that lands three hours late, into a day when every brand is mailing, mostly buys complaints and unsubscribes.
Protect the customer from the recovery
Late sends and catch-up runs are how people receive four messages in an afternoon. The pipeline recovers, several delayed jobs complete at once, and the frequency rules have to hold against all of them simultaneously.
Enforce the cap at the send layer, inside the engagement platform, not in the warehouse query that built the audience. A cap applied at audience build time knows nothing about the other three audiences built in the same ten minutes.
Then raise the standard for peak rather than relaxing it. Volumes are higher, tolerance is lower, and a customer who unsubscribes in the last week of November is gone for the whole of the following year.
Freeze the pipeline, not the calendar
Change freezes usually stop the wrong things. Marketing is told not to launch anything new, while the data team ships a schema change to the orders table because it is routine work.
Freeze the layers that feed sends: source schemas, transformation logic, audience definitions, sync configurations and platform-side field mappings. Leave the calendar flexible, because trading conditions change and the ability to add a send is worth keeping.
Set the freeze earlier than feels necessary. A fortnight before the first major date gives you time to find what the freeze broke, which is a thing freezes reliably do.
One more habit, cheap and useful: run a full rehearsal on a normal week. Build the peak audiences, run the syncs, send to seed addresses, and time every step. The rehearsal finds the ninety-minute job nobody knew about, while there is still time to shorten it.