Case study · Food-grade freight

Kan-Haul LoadTracker

AI-Assisted PHP Upgrade of a Legacy Web App

We have supported Kan-Haul's LoadTracker since 2016. In 2026 we used AI to move it from PHP 5.4 to 8.3, proving each change against the original page by page.

Overview

Kan-Haul is a food-grade freight company that moves shipments such as wine and other beverages for its clients, domestically and internationally, with roots its website traces back more than 100 years. LoadTracker is the web application it runs those shipments on: carriers, clients, jobs, load status updates and the confirmation sheets that go with them. Kan-Haul's staff use it every day, and its customers use it to track their shipments from pickup to delivery. It holds more than 22,000 jobs and 232,000 load status updates.

We did not build LoadTracker. We took it on in 2016, when Kan-Haul needed a team to support it. We have kept it running ever since, through a hosting move, feature work, security certificates and an operating system end of life. In 2026 we took on the biggest job yet: bringing the whole application onto a modern, supported stack.

The Challenge

Every layer of LoadTracker had passed its end of life. It ran on PHP 5.4, which stopped receiving security fixes in 2015, on an equally old database, web server and operating system. The code was written without a framework, without dependency management and without a single automated test. Some of its bundled libraries were more than fifteen years old.

That combination is what makes old applications dangerous to touch. An automated scan found 593 compatibility problems across 342 files that would break on modern PHP, most of them in how the application talks to its database. With no tests, there was no quick way to prove that a change had not broken something a dispatcher relies on.

A test suite the app never had. Two copies of the application run side by side on the same data. Every page and PDF is compared, so a change that alters what users see cannot slip through.

What We Built

An audit before any code changed

We catalogued the application: which files were actually in use, which libraries were bundled and which were dead, where the security and data risks were, and what a modern stack would need. That audit set the plan and the estimate, and it separated a like-for-like port from improvements that needed Kan-Haul's approval.

Two copies of the application, side by side

We set up the old application exactly as production runs it, frozen and never edited, and next to it an upgrade copy on PHP 8.3 and MySQL 8.0. Both load the same snapshot of production data. Comparison scripts diff the rendered pages of about 55 screens and every generated PDF between the two, so any difference in what users see has to be explained before it is accepted. That became the test suite the application never had.

AI doing the repetitive conversion, people deciding

Claude Code, Anthropic's AI coding tool, did the bulk of the mechanical conversion work in structured sessions: the database layer, retired PHP functions, files that no longer parsed and the errors modern PHP no longer tolerates. It also wrote the comparison and verification scripts, and drove a real browser to test the application the way a person would, which caught a login problem that automated page checks could not see. An automated conversion tool was tested and rejected when it produced incorrect code. Every change beyond a straight port, such as how passwords are stored, needed a person's approval, and the frozen legacy copy stayed off-limits to the AI.

Fixing what the port uncovered

Rebuilding the reports and PDF generation on current libraries, moving the database to strict mode and full Unicode, and fixing real bugs the comparison exposed, including one that could silently clear a job's carrier when the job was edited. Security problems found in the audit are fixed in the upgraded version rather than just reported.

Faster, too

A single missing database index was making the main jobs screen take 56 seconds to load. With the index added it loads in under two seconds, with exactly the same output. A load tracking report that the old stack could not finish in seven minutes completes in under a minute.

Results

  • The upgraded application is complete and in final testing ahead of its move to a new server.
  • A like-for-like port confirmed by page-by-page and PDF-by-PDF comparison against the original, not by hoping nothing broke.
  • The main jobs screen went from 56 seconds to under two.
  • Ten years of support for an application we inherited, now on a stack that receives security updates again.