All Articles
technical

Our CargoWise Sync Needed 33 Seconds. Netlify Killed It at 26.

A real production postmortem: three sequential eAdapter calls vs a serverless wall-clock limit — and the timeout budgets, endpoint splitting, and partial-failure flags that fixed it.

Our CargoWise Sync Needed 33 Seconds. Netlify Killed It at 26.

In March 2026, a production CargoWise sync started failing — not always, just often enough to hurt. The booking sync made three sequential eAdapter calls, and on CargoWise's bad days those calls stacked up to 33 seconds. The Netlify function running them was killed at 26.

It's the default architecture almost everyone ships first: one endpoint, N sequential upstream calls, and a platform limit nobody re-read after the demo worked. Three facts collide in production:

  1. CargoWise response times are not yours to control. A busy instance can turn a 2-second call into a 20-second one.
  2. Serverless platforms enforce hard wall-clock limits. Your function doesn't degrade — it's terminated mid-flight.
  3. Sequential calls share one budget. Every slow call steals time from the calls behind it.

And a killed function is worse than a failed one: the first CargoWise push may have already succeeded — the job exists in CW, but your database never heard back.

Fix 1: no CargoWise call without a timeout budget

Nine endpoints that called CW with no timeout got an AbortController with an explicit budget (March 23: 9 files changed, 55 lines added). The numbers that shipped: 12s for the first XUS push (CW creates the Consol job — the expensive call), 8s for the S-number update, 15s for bulk Native XML queries, 10s for interactive carrier search.

Query endpoints need timeouts more than pushes: CW's Native XML queries don't paginate, so a wide date range returns megabytes and stalls both the transfer and your parser.

Fix 2: split sequential calls into independent endpoints

Timeouts stop one call eating the budget; the 33-second problem was structural. The split gave each CargoWise call its own serverless invocation with its own 20-second budget, with the frontend orchestrating the sequence — visible progress labels included.

The split forces you to define partial-failure semantics per step:

  • The first XUS succeeding is sacred — later failures must never mask it.
  • A failed S-number step sets a needs_second_sync flag and surfaces a retry action.
  • In serverless, await your side-effects — a runtime may freeze the instant the response returns, and un-awaited work silently never happens.

Know both of your platform's numbers

This war story spans two limits: Netlify's 10-second default and its 26-second extended limit. Budget against the one your function actually runs under — and re-check it when the platform changes plans.


Chapter 7 of eAdapter in Production has the full discipline: the complete budget table, backoff and circuit breakers, and credential health as infrastructure. Get Vol 2 →

Ready to automate your document processing?

Join freight forwarders saving hours every week with CargoMode.

Start for free