Slow network
The page that sometimes did not open
Some people said the app "sometimes does not open". The server had no errors. The cause was in the browser: network requests had no time limit. On a weak connection a request could hang without failing, and the loading screen stayed forever.
Fix: every request now has a time limit (15 seconds to read, 60 to write), the service worker serves the saved page after 4 seconds, and the app opens from its local copy and recovers by itself. A real-browser test reproduces the hang. The old version never opened in 25 seconds. The new one opened in 4.2 seconds.
A request that never fails is worse than one that fails.
Database
The security fix that slowed every read
A security change made a permission check run once for every row. Reading the shipments table went from 102 ms to 432 ms in a local test with 3,000 shipments. The change had not been timed before release.
Fix: the check was wrapped so the database runs it once per query. Reading dropped to 5 ms. Now every SQL change is timed before and after, and a test checks the wrapped form.
Time a change before you call it safe.
Data model
One truck, two delivery notes
When one truck carried two delivery notes to the same address, staff split the carrier's price by hand and typed a part into each note. Each part then looked like a cheap trip. The price check and the suggestions slowly drifted low.
Fix: the price is typed once for the truck and split by weight. Price checks count the truck as one trip. If one note is cancelled, the others share the price.
Model the real thing (one truck), not the paperwork (two documents).
Testing
The safety net that quietly stopped working
One end-to-end test guards the sync between phone and server. A screen redesign changed the page structure, and the test started failing on its first line. Nobody saw it from version 2.69 to 2.80, because it ran only when someone asked for it.
Fix: the test was rewritten against the new screens and now passes all 33 checks. Any change to the sync code requires it to pass.
A check nobody runs is not a check.
Business rule
One box, two meanings
Each quote has a promised delivery time in days. An empty box was saved as 0, and 0 also meant "delivered on the day it leaves", so the two could not be told apart. Three screens also measured lateness in three ways: for a one-day promise, one screen marked a trip late after 24 hours and the other two after 36.
Fix: the rule now lives in one module and counts calendar days. 0 is the day the truck leaves, 1 is the next day, an empty box means no promise. A trip is late only after the promised day has ended. A one-time migration turned the old zeros back into empty boxes.
One rule, written in one place.
Email
The email that looked right in the browser
The first order email looked fine in a browser preview. In Outlook it was stretched across the whole window, text was squeezed together, and the logo vanished into the header of the same colour. Outlook draws email with the Word engine, which ignores a maximum width and does not keep padding on text blocks.
Fix: the email now has a fixed width, the spacing is made of empty rows instead of padding, and the logo is gone. The design was checked against screenshots of the real Outlook window, over several rounds, until it fit.
Test where it will be read, not where it was written.