A code freeze is a promise that nothing changes. The point is to protect the peak season weeks that matter most.
Then something breaks the promise. A fix is urgent enough, or a promotion important enough, that leadership approves it anyway, freeze be damned. By the end of peak season, most ecommerce teams have a handful of these.
Adobe reports that US shoppers spent $44.2 billion online over Cyber Week 2025, up 7.7% from the year before, with a record $11.8 billion on Black Friday alone. That much revenue in five days makes peak the closest thing most teams get to a full-scale load test. The exception list records where it strained.
Incidents get postmortems, but the exceptions leadership approves rarely get read together. That’s the mistake. Read as a set, they show which past decisions are still costing you. They’re the start of next year’s technical debt roadmap.
Separate Technical Debt From Incidents
Technical debt is a past decision coming due. Ask two questions of every exception on the list:
- Was the trigger severe if something failed?
- Did a past decision contribute?
Severity tells you which ones to look at first. Whether a past decision contributed decides what goes on the roadmap, whatever the severity. That decision might be a shortcut, a deferred refactor, a known limitation, or a missing fallback that real load finally exposed.
Take Cloudflare’s outage on 18 November 2025, ten days before Black Friday. A database permissions change made a configuration file double in size. The software that read the file capped the features it would load at 200 against about 60 in use. It had no handling for a file over that cap. When the bad file arrived, the code failed, “resulting in the system panicking.” Cloudflare reported all systems back to normal almost six hours after it began.
Run the two questions on that outage. The trigger was severe, and a past decision contributed: nothing in the code handled a file over the cap.
Notice the second question asks whether a past decision contributed, not whether it caused the failure. The outage needed two things to go wrong at once: a permissions change and a missing check. Richard Cook, a physician and expert in how complex systems fail, made the general point more than two decades ago: “Post-accident attribution to a ‘root cause’ is fundamentally wrong.” Fix only the permissions change, and the missing check is still in the code.
Debt That Doesn’t Look Like a Failure
For a retailer behind Cloudflare, that day was someone else’s incident. The exception on its list is the change it pushed in response, such as rerouting traffic. The past decision to look at is the retailer’s own. What did it have in place if the content delivery network went down? If the answer was nothing, that gap goes on the retailer’s roadmap.
A retailer that waited it out made no change, so nothing shows up on its list, and the missing fallback never gets weighed for the roadmap. That’s why the sort list below starts by pulling in your most severe incidents from the log.
Some exceptions aren’t fixes at all. A promotion or a price change that couldn’t wait for January still needed an emergency change. If routine merchandising work needs a deployment in the middle of peak, your merchandisers can’t change the site without engineering. Somebody decided long ago that those changes go through a deployment, and that decision belongs on the roadmap.
Where Past Decisions Show Up as Patterns
Checkout Customizations
A synchronous call or a customization in the checkout path works at normal volume and fails when concurrency climbs: the module that was fine in March and fails on the Friday after Thanksgiving. A failing checkout loses orders directly, so it’s usually the first exception anyone approves.
Syncs that Run on an Interval
When commerce syncs with the order management system on an interval, peak traffic widens the gap between what the storefront shows and what the warehouse holds. Nothing errors while the data is behind. Two systems hold different truths about the same product, and customers buy what isn’t there. It gets logged as an operations problem, but it’s an integration design problem and will usually be back at the next peak.
Limit Nobody Sized for Peak
A rate limit on a tax, payment, or shipping service, or a database connection pool sized for normal traffic, runs fine for years because it never reaches the number that breaks it. Nobody stress-tested past that line, so nobody knew it existed until peak season found it.
In each case, someone patched it to get through the weekend, and the checkout customization, the sync interval, or the unsized limit is still there on January 2.
What an Unread List Costs
If nobody sorts the season’s exceptions by whether a past decision contributed, next year’s roadmap goes to whoever escalates the loudest incident, not to what recurs or costs the most. You already paid for that list in engineering hours and approvals under pressure. Throwing it away means paying for it twice.
Before the Freeze
The only new work during peak is recording each exception as it happens. Before the freeze, set up a freeze-exception tag in your change tool, whether that’s ServiceNow, Jira, or a shared sheet. Each tagged record needs:
- The system affected
- What changed, and what failed if something did
- The severity of the trigger, if something failed
- Why it couldn’t wait
- What it cost while it lasted, such as downtime or orders affected
- The workaround left in place
During the freeze, set up a weekly cadence to tag each exception, one sentence per field.
After the Freeze
Soon after the freeze lifts, sort the list:
- Add your most severe incidents from the incident log.
- Group everything by the system it touched. Several exceptions on one system are often one of the patterns above showing up more than once.
- Starting with the most severe, ask of each exception or group whether a past decision contributed.
- Label unclear calls unclear rather than guess.
Then rank what lands on the roadmap by cost of delay, which you can estimate yourself:
- Revenue at risk: what the failure cost while it lasted, and what an hour of it would cost next peak
- Likelihood of recurrence: whether next peak will trigger it again
- Cost of carrying it: manual workarounds, on-call hours, orders fixed by hand
- Initiatives blocked: planned work that builds on the weak point and can’t safely ship until the fix lands
Take the ranked list to your leadership team and open with two numbers: how many times you broke the freeze this peak, and how many items trace back to technical debt. Think of the checkout customization nobody wants to touch, the inventory sync that runs every 15 minutes, or the API limit sized for an ordinary Tuesday. List the Unclear exceptions beside that number, not in it. One inflated figure undermines everything else you say. For the top items, show the revenue at risk and the hours spent keeping each one alive. Then ask for roadmap time to size and fund the fixes. Without it, you’re not avoiding the next freeze break. You’re scheduling it.
Where Sorting Stops, Analysis Starts
Sorting shows you the weak points and what the delay costs. It doesn’t tell you the right fix, or how long it takes. That requires analysis against your actual architecture. The same analysis shows which planned initiatives depend on each weak point. Fixes that can’t land before the next peak need a mitigation plan instead.
Once effort is known, the ranking becomes Weighted Shortest Job First, “the relative cost of delay divided by the relative job duration.” You already have the cost of delay, and the analysis supplies the duration. Sorted, ranked, and sized, technical debt stops being an argument and becomes a priority list.

