Economics Journal

Kirchner working paper · ocean bills of lading · 22 August 2026

Did COVID permanently raise supplier turnover among large US importers?

A six-year vs six-year comparison (2014–2019 against 2020–2025) of supplier add and leave rates for ten major US ocean importers in distinct industries, measured on Kirchner’s CBP bill-of-lading corpus. Methods and queries first; interpretation last.

Snapshot generated 2026-08-22T15:29:17+00:00 from kirchner.bols. Tool: Supplier turnover study. Runner: scripts/run-covid-supplier-churn.php.

1. Test

The object is a consignee–shipper pair on a US ocean bill of lading. For importer i and calendar year t, a foreign supplier (the shipper_name field, uppercased and trimmed) is active if it appears on at least one bill of lading to that importer in year t. Empty and placeholder shipper names (N/A, NONE, NULL, UNKNOWN, length < 3) are dropped.

The two windows are inclusive calendar years 2014–2019 and 2020–2025. Those are six-year spans whose endpoints are five years apart. The test uses the five year-to-year transitions inside each window:

  • Pre-COVID transitions: 2014→2015, 2015→2016, 2016→2017, 2017→2018, 2018→2019.
  • COVID and after: 2020→2021, 2021→2022, 2022→2023, 2023→2024, 2024→2025.

For a transition t → t+1:

  • Left = suppliers active in t and absent in t+1.
  • Added = suppliers active in t+1 and absent in t.
  • Exit rate = left / number of suppliers in t.
  • Add rate = added / number of suppliers in t.

The 2019→2020 step is the onset year. It is stored but excluded from period means, so a one-year lockdown shock is not averaged into either five-transition window.

A second, slower test compares supplier sets at the ends of each window: unique shippers in 2014–2015 versus 2018–2019, and 2020–2021 versus 2024–2025. Added and left are set differences. That test asks whether the roster turned over across four years, not whether it flickered year to year.

Coverage filter (pre-specified after seeing yearly holes)

Raw consignee strings are unstable. A year in which Walmart almost vanishes from WALMART INC is not a year in which Walmart fired its factories. After Check 3 showed those holes, every year is marked usable only if unique bills of lading for that importer are at least max(100, 0.25 × that importer’s median yearly BOL count). A transition is usable only if both years are usable. Period means use usable transitions only. Apple drops out of the paired YoY comparison because no post-2020 year clears the threshold.

Consignee names containing CANADA, MEXICO, DE MEXICO, or S DE R L are dropped so the sample is US-bound filings, not Mexican or Canadian affiliates that happen to match the prefix.

2. Data and runner

Source: Kirchner kirchner.bols on ClickHouse, the same ocean AMS/CBP bills of lading served by company analysis. The runner is scripts/run-covid-supplier-churn.php. It prints every SQL statement before executing it and writes config/research-covid-supplier-churn.json. The interactive copy of that snapshot is /research-covid-supplier-churn.

Limitations that are features of the legal dataset, not of this script: US public bills of lading are ocean only; HS codes on these rows are not official Census HTS; firms may request name redaction; shipper strings are not parent-resolved.

3. Checks (query, then result)

Check 0 — corpus coverage, 2014–2025

Does the table actually contain both windows?

SELECT min(actual_arrival_date) AS min_date, max(actual_arrival_date) AS max_date,
  count() AS rows, uniqExact(bill_of_lading) AS unique_bols
FROM bols
WHERE actual_arrival_date >= toDate('2014-01-01') AND actual_arrival_date <= toDate('2025-12-31')
Min dateMax dateRowsUnique BOLs
2014-01-01 2025-12-31 173,043,175 158,548,137
SELECT toYear(actual_arrival_date) AS year, count() AS rows, uniqExact(bill_of_lading) AS unique_bols
FROM bols
WHERE actual_arrival_date >= toDate('2014-01-01') AND actual_arrival_date <= toDate('2025-12-31')
GROUP BY year ORDER BY year
YearRowsUnique BOLs
2014 11,235,494 10,685,269
2015 11,317,661 10,763,968
2016 11,529,522 10,902,902
2017 12,185,128 11,342,408
2018 12,950,900 12,130,298
2019 12,649,876 11,991,418
2020 13,773,553 12,620,768
2021 16,422,482 13,798,798
2022 16,922,821 13,933,642
2023 14,553,002 13,230,371
2024 19,122,279 17,330,181
2025 20,380,457 20,017,014

The corpus covers every calendar year in both windows. Unique bills of lading rise from 10,685,269 in 2014 to 20,017,014 in 2025. 2025 is not a stub year in this snapshot.

Check 1 — importer names, then the ten-firm sample

Fourteen candidate brands were searched with explicit startsWith(upperUTF8(consignee_name), …) prefixes. US-name filter applied. A variant is kept if it has at least 200 bills in 2014–2025 and is among the top three names or at least 5% of the top name. The analysis sample is ten firms in different industries that clear 200 bills in both windows. Starbucks, Sephora, lululemon, and Pfizer were screened (see the tool). Walmart’s discovery query:

SELECT consignee_name AS name,
  uniqExactIf(bill_of_lading, actual_arrival_date >= toDate('2014-01-01') AND actual_arrival_date <= toDate('2019-12-31')) AS bols_2014_2019,
  uniqExactIf(bill_of_lading, actual_arrival_date >= toDate('2020-01-01') AND actual_arrival_date <= toDate('2025-12-31')) AS bols_2020_2025,
  uniqExact(bill_of_lading) AS bols_2014_2025
FROM bols
WHERE actual_arrival_date >= toDate('2014-01-01') AND actual_arrival_date <= toDate('2025-12-31')
  AND (startsWith(upperUTF8(consignee_name), 'WALMART') OR startsWith(upperUTF8(consignee_name), 'WAL-MART'))
GROUP BY name
ORDER BY bols_2014_2025 DESC
LIMIT 20
Importer Industry Locked consignee names
Walmart General merchandise retail WALMART INC; WALMART STORES INC; WALMART GLOBAL LOGISTICS
The Home Depot Home improvement retail HOME DEPOT USA INC; HOME DEPOT USA; THE HOME DEPOT INC
IKEA Furniture / home furnishings IKEA SUPPLY AG; IKEA DISTRIBUTION SERVICES INC; IKEA DISTRIBUTION SERVICES INC L
Nike Athletic apparel and footwear NIKE USA INC; NIKE INC; NIKE EUROPEAN OPERATIONS
Tesla Electric vehicles TESLA INC; TESLA MOTORS INC; TESLA MOTORS
Apple Consumer electronics APPLE INC; APPLE COMPUTER INC
Intel Semiconductors INTEL CORP
Costco Warehouse club retail COSTCO WHOLESALE CORP; COSTCO WHOLESALE; COSTCO WHOLESALE COPRORATION
Toyota Automotive manufacturing TOYOTA MOTOR SALES USA; TOYOTA MOTOR SALES USA INC; TOYOTA MOTOR MANUFACTURING KENTUCKY INC; TOYOTA MOTOR MANUFACTURING INDIANA INC; TOYOTA MOTOR MANUFACTURING; TOYOTA MOTOR MANUFACTURING WEST VIRGINIA INC; TOYOTA MOTOR MANUFACTURING TEXAS INC; TOYOTA MOTOR MANUFACTURING KENTUCKY; TOYOTA MOTOR MANUFACTURING MISSISSIPPI INC; TOYOTA MOTOR MANUFACTURING INDIANA; TOYOTA MOTOR MANUFACTURING WEST VI; TOYOTA MOTOR CORP; TOYOTA MOTOR MANUFACTURING ALABAMA INC; TOYOTA MOTOR MANUFACTURING MISSISSI; TOYOTA MOTOR MANUFACTURING ALABAMA; TOYOTA MOTOR MANUFACTURING TEXAS IN
Mattel Toys MATTEL INC; MATTEL IMPORT SERVICES CORP; MATTEL IMPORT SERVICES LLC; MATTEL INCORPORATED

Nike’s locked list includes NIKE EUROPEAN OPERATIONS, which the geographic filter did not catch. IKEA’s top consignee is IKEA SUPPLY AG (the filing name on US ocean bills, not a US corporation). Those are disclosed, not cleaned after the fact.

Check 2 — bills and unique suppliers by window

Same SELECT, one consignee_name IN (…) list per firm. Example (Walmart):

SELECT
  uniqExactIf(bill_of_lading, actual_arrival_date >= toDate('2014-01-01') AND actual_arrival_date <= toDate('2019-12-31')) AS bols_pre,
  uniqExactIf(bill_of_lading, actual_arrival_date >= toDate('2020-01-01') AND actual_arrival_date <= toDate('2025-12-31')) AS bols_post,
  uniqExactIf(upperUTF8(trimBoth(shipper_name)), actual_arrival_date >= toDate('2014-01-01') AND actual_arrival_date <= toDate('2019-12-31') AND trimBoth(shipper_name) != '' AND lengthUTF8(trimBoth(shipper_name)) >= 3 AND upperUTF8(trimBoth(shipper_name)) NOT IN ('N/A','NA','NONE','NULL','UNKNOWN','-','--','N.A.')) AS suppliers_pre,
  uniqExactIf(upperUTF8(trimBoth(shipper_name)), actual_arrival_date >= toDate('2020-01-01') AND actual_arrival_date <= toDate('2025-12-31') AND trimBoth(shipper_name) != '' AND lengthUTF8(trimBoth(shipper_name)) >= 3 AND upperUTF8(trimBoth(shipper_name)) NOT IN ('N/A','NA','NONE','NULL','UNKNOWN','-','--','N.A.')) AS suppliers_post
FROM bols
WHERE consignee_name IN ('WALMART INC','WALMART STORES INC','WALMART GLOBAL LOGISTICS')
  AND actual_arrival_date >= toDate('2014-01-01') AND actual_arrival_date <= toDate('2025-12-31')
Importer BOLs 2014–19 BOLs 2020–25 Suppliers 2014–19 Suppliers 2020–25
Walmart 120,723 182,609 3,403 1,427
The Home Depot 124,053 107,568 1,877 1,684
IKEA 323,961 763,728 2,287 3,251
Nike 1,862 129,928 59 753
Tesla 6,774 36,111 327 1,287
Apple 6,160 1,083 87 95
Intel 2,448 3,446 135 176
Costco 146,746 21,965 2,322 615
Toyota 15,593 14,553 59 51
Mattel 42,531 32,910 477 352

Two facts from the table, not from narrative. Walmart’s unique shipper count falls from 3,403 to 1,427 while bills rise. Apple’s ocean bills collapse from 6,160 to 1,083 — consistent with electronics moving by air, which this dataset cannot see.

Check 3 — yearly series (why a coverage filter is required)

IKEA is the clean series. Walmart is the warning. Queries are the same shape; both are printed.

IKEA

SELECT toYear(actual_arrival_date) AS year,
  uniqExact(bill_of_lading) AS bols,
  uniqExactIf(upperUTF8(trimBoth(shipper_name)), trimBoth(shipper_name) != '' AND lengthUTF8(trimBoth(shipper_name)) >= 3 AND upperUTF8(trimBoth(shipper_name)) NOT IN ('N/A','NA','NONE','NULL','UNKNOWN','-','--','N.A.')) AS suppliers
FROM bols
WHERE consignee_name IN ('IKEA SUPPLY AG','IKEA DISTRIBUTION SERVICES INC','IKEA DISTRIBUTION SERVICES INC L')
  AND actual_arrival_date >= toDate('2014-01-01') AND actual_arrival_date <= toDate('2025-12-31')
GROUP BY year ORDER BY year
YearBOLsSuppliers
2014 32,756 794
2015 38,068 822
2016 38,123 709
2017 40,241 758
2018 77,059 1,123
2019 97,902 1,242
2020 97,466 1,259
2021 125,189 1,400
2022 139,556 1,701
2023 135,096 1,491
2024 119,611 1,449
2025 147,464 1,256

Walmart

SELECT toYear(actual_arrival_date) AS year,
  uniqExact(bill_of_lading) AS bols,
  uniqExactIf(upperUTF8(trimBoth(shipper_name)), trimBoth(shipper_name) != '' AND lengthUTF8(trimBoth(shipper_name)) >= 3 AND upperUTF8(trimBoth(shipper_name)) NOT IN ('N/A','NA','NONE','NULL','UNKNOWN','-','--','N.A.')) AS suppliers
FROM bols
WHERE consignee_name IN ('WALMART INC','WALMART STORES INC','WALMART GLOBAL LOGISTICS')
  AND actual_arrival_date >= toDate('2014-01-01') AND actual_arrival_date <= toDate('2025-12-31')
GROUP BY year ORDER BY year
YearBOLsSuppliers
2014 6,388 118
2015 4,929 184
2016 1,849 206
2017 437 42
2018 26,115 946
2019 81,006 2,813
2020 24,697 525
2021 32,546 626
2022 29,553 579
2023 34,568 508
2024 32,042 430
2025 29,203 399

Walmart 2017 is 437 bills and 42 shippers against 81,006 bills and 2,813 shippers in 2019. That is a filing-name hole, not de-globalization. Home Depot 2020 shows the same pattern. Treating those years as mass supplier exit would invent a COVID result. The coverage filter exists to refuse that invention.

Check 4 — year-to-year left and added

Two queries, no correlated subqueries. Left/stayed from a left join of year t onto t+1; added from a left join of t+1 onto t. Walmart’s pair:

WITH base AS (
  SELECT toYear(actual_arrival_date) AS y, upperUTF8(trimBoth(shipper_name)) AS shipper
  FROM bols
  WHERE consignee_name IN ('WALMART INC','WALMART STORES INC','WALMART GLOBAL LOGISTICS')
    AND actual_arrival_date >= toDate('2014-01-01') AND actual_arrival_date <= toDate('2025-12-31')
    AND trimBoth(shipper_name) != '' AND lengthUTF8(trimBoth(shipper_name)) >= 3 AND upperUTF8(trimBoth(shipper_name)) NOT IN ('N/A','NA','NONE','NULL','UNKNOWN','-','--','N.A.')
  GROUP BY y, shipper
)
SELECT p.y AS year_from, p.y + 1 AS year_to,
  uniqExact(p.shipper) AS suppliers_from,
  uniqExactIf(p.shipper, c.shipper != '') AS stayed,
  uniqExact(p.shipper) - uniqExactIf(p.shipper, c.shipper != '') AS left_count
FROM base AS p
LEFT JOIN base AS c ON p.shipper = c.shipper AND c.y = p.y + 1
WHERE p.y >= 2014 AND p.y <= 2024
GROUP BY p.y ORDER BY p.y
WITH base AS (
  SELECT toYear(actual_arrival_date) AS y, upperUTF8(trimBoth(shipper_name)) AS shipper
  FROM bols
  WHERE consignee_name IN ('WALMART INC','WALMART STORES INC','WALMART GLOBAL LOGISTICS')
    AND actual_arrival_date >= toDate('2014-01-01') AND actual_arrival_date <= toDate('2025-12-31')
    AND trimBoth(shipper_name) != '' AND lengthUTF8(trimBoth(shipper_name)) >= 3 AND upperUTF8(trimBoth(shipper_name)) NOT IN ('N/A','NA','NONE','NULL','UNKNOWN','-','--','N.A.')
  GROUP BY y, shipper
)
SELECT c.y - 1 AS year_from, c.y AS year_to,
  uniqExact(c.shipper) AS suppliers_to,
  uniqExactIf(c.shipper, p.shipper = '') AS added_count
FROM base AS c
LEFT JOIN base AS p ON c.shipper = p.shipper AND p.y = c.y - 1
WHERE c.y >= 2015 AND c.y <= 2025
GROUP BY c.y ORDER BY c.y

Every importer’s YoY rows, usable flag, and threshold are in the tool. Period means below use only usable transitions.

Check 5 — four-year set turnover

WITH base AS (
  SELECT toYear(actual_arrival_date) AS y, upperUTF8(trimBoth(shipper_name)) AS shipper
  FROM bols
  WHERE consignee_name IN ('IKEA SUPPLY AG','IKEA DISTRIBUTION SERVICES INC','IKEA DISTRIBUTION SERVICES INC L')
    AND actual_arrival_date >= toDate('2014-01-01') AND actual_arrival_date <= toDate('2025-12-31')
    AND trimBoth(shipper_name) != '' AND lengthUTF8(trimBoth(shipper_name)) >= 3 AND upperUTF8(trimBoth(shipper_name)) NOT IN ('N/A','NA','NONE','NULL','UNKNOWN','-','--','N.A.')
  GROUP BY y, shipper
),
pre_early AS (SELECT DISTINCT shipper FROM base WHERE y IN (2014, 2015)),
pre_late  AS (SELECT DISTINCT shipper FROM base WHERE y IN (2018, 2019)),
post_early AS (SELECT DISTINCT shipper FROM base WHERE y IN (2020, 2021)),
post_late  AS (SELECT DISTINCT shipper FROM base WHERE y IN (2024, 2025))
SELECT
  (SELECT count() FROM pre_early) AS pre_early_n,
  (SELECT count() FROM pre_late) AS pre_late_n,
  (SELECT count() FROM pre_early INNER JOIN pre_late USING shipper) AS pre_stayed,
  (SELECT count() FROM pre_early) - (SELECT count() FROM pre_early INNER JOIN pre_late USING shipper) AS pre_left,
  (SELECT count() FROM pre_late) - (SELECT count() FROM pre_early INNER JOIN pre_late USING shipper) AS pre_added,
  (SELECT count() FROM post_early) AS post_early_n,
  (SELECT count() FROM post_late) AS post_late_n,
  (SELECT count() FROM post_early INNER JOIN post_late USING shipper) AS post_stayed,
  (SELECT count() FROM post_early) - (SELECT count() FROM post_early INNER JOIN post_late USING shipper) AS post_left,
  (SELECT count() FROM post_late) - (SELECT count() FROM post_early INNER JOIN post_late USING shipper) AS post_added
Importer Pre exit
14–15 → 18–19
Pre add Post exit
20–21 → 24–25
Post add
Walmart 56.1% 1,299.6% 69.8% 34.2%
The Home Depot 69.5% 69.9% 68.3% 115.0%
IKEA 51.9% 91.3% 50.4% 59.1%
Nike 97.8% 3.7%
Tesla 98.5% 8.1% 76.4% 1,180.0%
Apple 60.7% 110.7% 83.3% 88.1%
Intel 65.7% 84.3% 55.6% 175.9%
Costco 89.1% 30.2% 85.0% 44.4%
Toyota 54.8% 51.6% 54.8% 35.5%
Mattel 72.2% 50.2% 67.0% 36.5%

4. Test outcome

Paired YoY means (coverage-filtered). Apple has no usable post-2020 transitions, so n = 9 of 10 firms.

Importer Usable trans. pre Usable trans. post Mean exit pre Mean exit post Δ exit Mean add pre Mean add post Δ add
Walmart 1 5 39.2% 41.7% 2.5% 236.6% 37.1% -199.5%
The Home Depot 3 4 59.3% 56.6% -2.7% 94.9% 356.7% 261.8%
IKEA 5 5 31.8% 29.6% -2.2% 42.9% 30.5% -12.4%
Nike 1 1 85.7% 32.5% -53.2% 66.7% 84.0% 17.3%
Tesla 3 5 56.8% 66.2% 9.4% 43.7% 666.7% 623.0%
Apple 5 0 51.3% 70.3%
Intel 3 3 40.8% 59.5% 18.7% 75.8% 43.6% -32.3%
Costco 5 2 60.2% 64.7% 4.5% 70.9% 62.2% -8.7%
Toyota 5 5 42.3% 37.7% -4.6% 47.7% 38.9% -8.8%
Mattel 5 4 45.3% 40.0% -5.4% 46.6% 43.0% -3.7%
Equal-weight mean across firms with both periodsPrePostPost − pre
YoY exit rate 51.3% 47.6% -3.7%
YoY add rate 80.6% 151.4% 70.8%
Four-year set exit (n = 9) see Check 5 -0.9%
Four-year set add see Check 5 -3.0%

Exit rates did not rise. The nine-firm mean exit rate is 51.3% before COVID and 47.6% after (Δ -3.7%). The four-year set test agrees: Δ exit -0.9%.

Add rates look higher in the nine-firm mean because of two spikes (Tesla Δ add 623.0%, Home Depot Δ add 261.8%). Tesla’s 2023 shipper count jumps from 53 to 880 then collapses in 2024 — the same family of coverage/scale artifacts as Walmart 2017. The four-year set add rate falls slightly (Δ -3.0%).

Balanced subsample (at least four usable transitions in each window)

Firms that survive that cut: IKEA, Toyota, Mattel. Mean exit 39.8% → 35.8% (Δ -4.0%). Mean add 45.7% → 37.4% (Δ -8.3%). On the series that can actually be compared year by year, both adding and leaving decline after 2020.

5. Meaning of the outcome

If COVID had permanently scrambled who sells to whom on US ocean lanes, exit rates in 2020–2025 would exceed 2014–2019. They do not. Among IKEA, Toyota, and Mattel — the three firms with dense, usable coverage in both windows — the supplier roster is slightly more persistent after 2020 than before. That is the opposite of a long-run “reset.”

What the unfiltered series would have said is different and false. Walmart 2017 and Home Depot 2020 look like mass exits if you do not look at bill counts. Those holes are consignee-name practice (and possibly confidentiality), the same problem ImportYeti tutorials hit when a brand’s LLC does not match the BOL. A coverage filter is not optional for this dataset.

Tesla’s post-2020 add spike is real in the table and unreliable as a general COVID fact. The firm’s ocean consignee identity and volume are not stationary. Apple’s ocean bills shrink; that is a mode-of-transport fact, not a supplier-turnover fact. Costco’s US-name ocean volume is much lower in 2020–2025 than in 2014–2019; whether that is naming, channel shift, or sourcing is not identified here.

Relative to Flaaen et al. (Fed FEDS 2021-066), who show that the 2020 collapse was extensive-margin (pairs dying) and the rebound intensive-margin (same pairs shipping more), this paper asks a longer question: after the rebound, did large importers keep rotating factories? In ocean bills, for this sample, no.

6. Hypothesis (stated after the test)

This is a post-hoc hypothesis, labeled as such. It is what the checks support, not what was promised in advance.

H. Conditional on a US ocean consignee identity that is observed in both 2014–2019 and 2020–2025, year-to-year supplier exit rates are not higher in the COVID window than in the five preceding transitions. Apparent post-2020 “churn” in unfiltered name series is mostly coverage holes and a small number of non-stationary identities (notably Tesla), not a durable increase in factory replacement.

7. Introduction (written last)

Public US ocean bills of lading are one of the few firm-to-firm trade datasets that can be used outside a Census research data center. They are also messy: no official HS, missing values, redactions, and consignee strings that fragment. That mess is why platforms exist. It is also why a COVID “supply chain reset” story is easy to project onto a search box and hard to measure.

This paper takes ten large importers in different industries, locks the consignee strings actually present in Kirchner’s data, and asks how often those importers added or left ocean suppliers in 2014–2019 versus 2020–2025. The work is descriptive. The queries are public. The finding is narrower than the political sentence “COVID changed everything,” and more useful: among importers whose names we can track, supplier turnover did not permanently jump.

8. Further research

  • Parent-level entity resolution so WALMART INC and a 2017 spelling variant are one firm before churn is computed — the coverage filter is a stopgap, not a substitute.
  • Restrict pairs to a product family (description cluster or HS-with-confidence) so a retailer adding furniture factories is not counted as leaving an apparel mill.
  • Treat 2019→2020 as its own event study rather than excluding it from both means.
  • Match confidential / redacted bills; Apple and beauty retailers may have left the public file rather than the ocean.
  • Repeat the design for a random sample of mid-size consignees. Large incumbents may be exactly the firms that could keep factories.
  • Join vessel AIS as in Ganapati et al., to separate factory switching from routing switching.

Reproduce: open the study tool (every SQL from this snapshot) or run php scripts/run-covid-supplier-churn.php against kirchner.bols.