← All studies · askamerica.ai

Bigger trucking fleets show higher crash rates per mile in FMCSA's own data — the opposite of what per-driver metrics suggest

FMCSA Company Census File (transport.fmcsa_carriers), active carriers with a computed recordable_crash_rate and self-reported MCS-150 mileage

FMCSA Data Shows Bigger Trucking Fleets Report Higher Crash Rates Per Mile, No… Mileage-weighted recordable crash rate (per million self-reported MCS-150 miles) by carrier fleet size Rate ratio: 1000+ truck fleets vs 1-3 truck fleets ~3.4x higher 2.68 vs 0.79 crashes/million mi Mileage-weighted crash rate by fleet size (power units) 0.0 0.5 1.0 1.5 2.0 2.5 3.0 Fleet size (power units) Crashes / million mi 1-3 4-10 11-50 51-200 201-1000 1000+ Excludes sentinel/placeholder values (rate >= 900); weighted by each carrier's reported annual mileage. Same pattern using driver-count buckets (robustness check) 0.0 0.5 1.0 1.5 2.0 2.5 3.0 Fleet size (total drivers) Crashes / million mi 1-3 4-10 11-50 51-200 201-1000 1000+ Same computation bucketed by driver count instead of power units. Carriers with a usable crash-rate + mileage figure ~460,000 of 2.24M active carriers ~20% coverage AskAmerica · askamerica.ai
SVG

Summary

The honest answer is: it depends entirely on the denominator, and the two standard ways of measuring 'danger' disagree on direction. Using FMCSA's own Company Census File, where each active carrier's recordable_crash_rate is (per FMCSA's Crash Indicator methodology) built against self-reported MCS-150 annual mileage, the largest fleets (1,000+ power units) show a mileage-weighted crash rate of about 2.7 crashes per million miles, roughly 3-4x higher than the smallest fleets (1-3 power units, about 0.8 per million miles). That is the opposite of the common claim. Separately, trade-press analysis of FMCSA's SMS data using a per-driver denominator finds the opposite pattern: midsize carriers (250-500 drivers) running crash rates above 7%, some over 11%, versus 4.9-6.6% for large carriers (500+ drivers) — i.e., midsize riskier than large, by that metric. Neither of these is a clean 'small vs. big' verdict per truck-mile that survives its own data-quality problems, discussed below. If forced to answer only the per-mile question the title asks, the FMCSA census-file evidence points to large carriers being measurably more crash-prone per mile than the very smallest carriers, not less — but this rests on self-reported mileage that FMCSA itself flags as a weak point, so it should be read as suggestive, not definitive.

What the FMCSA data actually shows

transport.fmcsa_carriers is FMCSA's Company Census File (~4.47M rows total; ~2.24M carriers currently active). It carries fleet size (power_units, total_drivers), a per-carrier recordable_crash_rate, and self-reported annual mileage (mcs150_mileage) from the biennial MCS-150 filing. FMCSA's own Crash Indicator BASIC factsheet confirms mileage from the MCS-150 is the denominator used in this crash-rate calculation.

Only about 447,000 of 2.24M active carriers (~20%) carry a non-null recordable_crash_rate, and of those, the large majority show exactly 0 (no DOT-recordable crash in the trailing 24-month window) — unsurprising for single-truck operators with low absolute exposure. A small number of records carry an obvious sentinel/placeholder value of 999.99x, which is not a real rate and was excluded.

Bucketing active carriers by power units and weighting each carrier's rate by its own reported mileage (so the outcome isn't dominated by noise from thousands of tiny, near-zero-mileage operators) produces a rate that rises with fleet size: roughly 0.7-0.8 crashes per million miles for 1-10 truck fleets, climbing to about 2.5-2.7 per million miles for 200+ and 1,000+ truck fleets. Re-running the identical calculation bucketed by driver count instead of power units reproduces the same direction and similar magnitudes (0.68 to 2.84 per million miles), so the pattern is not an artifact of which fleet-size variable was chosen.

Why this conflicts with the common claim, and why neither number should be taken as final

Trade-press reporting (FreightWaves, drawing on FMCSA crash counts normalized by driver count rather than mileage) finds midsize carriers (250-500 drivers) posting per-driver crash rates above 7%, some over 11%, against 4.9-6.6% for large carriers (500+ drivers) over the same year-to-date window — i.e., a different ranking (midsize worse than large) on a different denominator (per driver, not per mile).

Both metrics have real weaknesses that could plausibly move the small-vs-large comparison: (1) Self-reported mileage is filed only every two years on the MCS-150 and FMCSA explicitly urges carriers to keep it current — a single-truck operator who has not updated a boilerplate mileage estimate in years introduces noise or bias in either direction into a per-mile rate; a large carrier's mileage, sourced from ELD/IFTA-grade fleet records, is more likely accurate but not necessarily lower. (2) Crash under-reporting to FMCSA runs an estimated 30-40% nationally per industry commentary, and reporting completeness itself may vary by carrier size and by which crashes get logged as DOT-recordable. (3) Small-denominator noise: among carriers that do log at least one recordable crash, the smallest fleets show far higher (and far noisier) per-carrier rates than large fleets — one crash against a tiny reported-mileage base swings the rate enormously — which is exactly why the mileage-weighted aggregate (rather than a simple average of each carrier's own rate) is the more defensible number, but it still inherits the same underlying self-report accuracy problem.

Given these confounds, the safest, narrowest claim the data supports is: in FMCSA's own census-file crash-rate field, using its own self-reported-mileage denominator, large fleets (1,000+ trucks) show roughly 3-4x the crash rate per mile of the very smallest fleets (1-3 trucks), and this holds up whether fleets are grouped by trucks or by drivers. This does not resolve to a single 'X times more dangerous' figure for 'small trucking companies' as a whole versus 'big carriers' as a whole, because the per-driver metric used elsewhere in the industry literature reverses the finding for the specific midsize-vs-large comparison, and both metrics carry real, FMCSA-acknowledged data-quality caveats that a defensible answer cannot paper over.

Every query behind this report

7 warehouse calls ran in this session, in order. Each is reproducible against the same snapshot.

query — 1 rows — 4046 ms
SELECT COUNT(*) AS total, COUNT(recordable_crash_rate) AS with_rate, COUNT(power_units) AS with_units FROM transport.fmcsa_carriers WHERE status_code = 'A'
query — 6 rows — 1261 ms
SELECT
  CASE
    WHEN power_units <= 3 THEN '1-3 (micro)'
    WHEN power_units <= 10 THEN '4-10 (small)'
    WHEN power_units <= 50 THEN '11-50 (mid)'
    WHEN power_units <= 200 THEN '51-200 (large-ish)'
    WHEN power_units <= 1000 THEN '201-1000 (large)'
    ELSE '1000+ (mega)'
  END AS fleet_bucket,
  MIN(power_units) AS min_units,
  COUNT(*) AS n_carriers,
  AVG(recordable_crash_rate) AS avg_crash_rate,
  median(recordable_crash_rate) AS median_crash_rate,
  SUM(power_units) AS total_power_units
FROM transport.fmcsa_carriers
WHERE status_code = 'A' AND recordable_crash_rate IS NOT NULL AND power_units > 0 AND recordable_crash_rate >= 0
GROUP BY
  CASE
    WHEN power_units <= 3 THEN '1-3 (micro)'
    WHEN power_units <= 10 THEN '4-10 (small)'
    WHEN power_units <= 50 THEN '11-50 (mid)'
    WHEN power_units <= 200 THEN '51-200 (large-ish)'
    WHEN power_units <= 1000 THEN '201-1000 (large)'
    ELSE '1000+ (mega)'
  END
ORDER BY min_units
query — 6 rows — 1569 ms
SELECT
  CASE
    WHEN power_units <= 3 THEN '1-3 (micro)'
    WHEN power_units <= 10 THEN '4-10 (small)'
    WHEN power_units <= 50 THEN '11-50 (mid)'
    WHEN power_units <= 200 THEN '51-200 (large-ish)'
    WHEN power_units <= 1000 THEN '201-1000 (large)'
    ELSE '1000+ (mega)'
  END AS fleet_bucket,
  COUNT(*) AS n_with_rate,
  SUM(CASE WHEN recordable_crash_rate = 0 THEN 1 ELSE 0 END) AS n_zero,
  SUM(CASE WHEN recordable_crash_rate > 0 THEN 1 ELSE 0 END) AS n_positive,
  quantile_cont(recordable_crash_rate, 0.9) AS p90,
  quantile_cont(recordable_crash_rate, 0.99) AS p99,
  MAX(recordable_crash_rate) AS max_rate
FROM transport.fmcsa_carriers
WHERE status_code = 'A' AND recordable_crash_rate IS NOT NULL AND power_units > 0
GROUP BY
  CASE
    WHEN power_units <= 3 THEN '1-3 (micro)'
    WHEN power_units <= 10 THEN '4-10 (small)'
    WHEN power_units <= 50 THEN '11-50 (mid)'
    WHEN power_units <= 200 THEN '51-200 (large-ish)'
    WHEN power_units <= 1000 THEN '201-1000 (large)'
    ELSE '1000+ (mega)'
  END
ORDER BY MIN(power_units)
query — 6 rows — 1047 ms
SELECT
  CASE
    WHEN power_units <= 3 THEN '1-3 (micro)'
    WHEN power_units <= 10 THEN '4-10 (small)'
    WHEN power_units <= 50 THEN '11-50 (mid)'
    WHEN power_units <= 200 THEN '51-200 (large-ish)'
    WHEN power_units <= 1000 THEN '201-1000 (large)'
    ELSE '1000+ (mega)'
  END AS fleet_bucket,
  COUNT(*) AS n_total,
  SUM(CASE WHEN recordable_crash_rate >= 900 THEN 1 ELSE 0 END) AS n_sentinel_900plus,
  AVG(CASE WHEN recordable_crash_rate < 900 THEN recordable_crash_rate END) AS avg_excl_sentinel,
  median(CASE WHEN recordable_crash_rate < 900 THEN recordable_crash_rate END) AS median_excl_sentinel,
  quantile_cont(CASE WHEN recordable_crash_rate < 900 THEN recordable_crash_rate END, 0.9) AS p90_excl,
  AVG(CASE WHEN recordable_crash_rate < 900 AND recordable_crash_rate > 0 THEN recordable_crash_rate END) AS avg_positive_excl_sentinel,
  COUNT(CASE WHEN recordable_crash_rate < 900 AND recordable_crash_rate > 0 THEN 1 END) AS n_positive_excl
FROM transport.fmcsa_carriers
WHERE status_code = 'A' AND recordable_crash_rate IS NOT NULL AND power_units > 0
GROUP BY
  CASE
    WHEN power_units <= 3 THEN '1-3 (micro)'
    WHEN power_units <= 10 THEN '4-10 (small)'
    WHEN power_units <= 50 THEN '11-50 (mid)'
    WHEN power_units <= 200 THEN '51-200 (large-ish)'
    WHEN power_units <= 1000 THEN '201-1000 (large)'
    ELSE '1000+ (mega)'
  END
ORDER BY MIN(power_units)
query — 2 rows — 26864 ms
SELECT
  CASE WHEN review_date IS NOT NULL THEN 'has_review' ELSE 'no_review' END AS reviewed,
  COUNT(*) AS n,
  SUM(CASE WHEN recordable_crash_rate IS NOT NULL THEN 1 ELSE 0 END) AS n_with_rate,
  AVG(power_units) AS avg_power_units
FROM transport.fmcsa_carriers
WHERE status_code = 'A'
GROUP BY CASE WHEN review_date IS NOT NULL THEN 'has_review' ELSE 'no_review' END
query — 6 rows — 2202 ms
SELECT
  CASE
    WHEN power_units <= 3 THEN '1-3 (micro)'
    WHEN power_units <= 10 THEN '4-10 (small)'
    WHEN power_units <= 50 THEN '11-50 (mid)'
    WHEN power_units <= 200 THEN '51-200 (large-ish)'
    WHEN power_units <= 1000 THEN '201-1000 (large)'
    ELSE '1000+ (mega)'
  END AS fleet_bucket,
  COUNT(*) AS n,
  SUM(mcs150_mileage) AS total_miles,
  SUM(recordable_crash_rate * mcs150_mileage) / NULLIF(SUM(mcs150_mileage),0) AS mileage_weighted_avg_rate,
  AVG(recordable_crash_rate) AS simple_avg_rate
FROM transport.fmcsa_carriers
WHERE status_code = 'A' AND recordable_crash_rate IS NOT NULL AND recordable_crash_rate < 900
  AND power_units > 0 AND mcs150_mileage IS NOT NULL AND mcs150_mileage > 0
GROUP BY
  CASE
    WHEN power_units <= 3 THEN '1-3 (micro)'
    WHEN power_units <= 10 THEN '4-10 (small)'
    WHEN power_units <= 50 THEN '11-50 (mid)'
    WHEN power_units <= 200 THEN '51-200 (large-ish)'
    WHEN power_units <= 1000 THEN '201-1000 (large)'
    ELSE '1000+ (mega)'
  END
ORDER BY MIN(power_units)
query — 6 rows — 1169 ms
SELECT
  CASE
    WHEN total_drivers <= 3 THEN '1-3 drivers'
    WHEN total_drivers <= 10 THEN '4-10'
    WHEN total_drivers <= 50 THEN '11-50'
    WHEN total_drivers <= 200 THEN '51-200'
    WHEN total_drivers <= 1000 THEN '201-1000'
    ELSE '1000+'
  END AS bucket,
  COUNT(*) AS n,
  SUM(mcs150_mileage) AS total_miles,
  SUM(recordable_crash_rate * mcs150_mileage) / NULLIF(SUM(mcs150_mileage),0) AS mileage_weighted_rate
FROM transport.fmcsa_carriers
WHERE status_code = 'A' AND recordable_crash_rate IS NOT NULL AND recordable_crash_rate < 900
  AND total_drivers > 0 AND mcs150_mileage IS NOT NULL AND mcs150_mileage > 0
GROUP BY
  CASE
    WHEN total_drivers <= 3 THEN '1-3 drivers'
    WHEN total_drivers <= 10 THEN '4-10'
    WHEN total_drivers <= 50 THEN '11-50'
    WHEN total_drivers <= 200 THEN '51-200'
    WHEN total_drivers <= 1000 THEN '201-1000'
    ELSE '1000+'
  END
ORDER BY MIN(total_drivers)

Sources

  1. FMCSA Company Census File (transport.fmcsa_carriers)
    Show SQL
    SELECT CASE WHEN power_units<=3 THEN '1-3' WHEN power_units<=10 THEN '4-10' WHEN power_units<=50 THEN '11-50' WHEN power_units<=200 THEN '51-200' WHEN power_units<=1000 THEN '201-1000' ELSE '1000+' END AS bucket, SUM(recordable_crash_rate*mcs150_mileage)/NULLIF(SUM(mcs150_mileage),0) AS mileage_weighted_rate FROM transport.fmcsa_carriers WHERE status_code='A' AND recordable_crash_rate IS NOT NULL AND recordable_crash_rate<900 AND power_units>0 AND mcs150_mileage>0 GROUP BY bucket
  2. FMCSA Crash Indicator BASIC Factsheet (methodology: MCS-150 mileage used in crash-rate calculation)
  3. FreightWaves: FMCSA crash data — most dangerous trucking carriers (per-driver crash rates by fleet size)
  4. FMCSA 2024 Pocket Guide to Large Truck and Bus Statistics