Archive
upgrades
-
MySQL 8.4 LTS, and the authentication plugin that ended the upgrade
The 8.0 to 8.4 in-place upgrade cost us 6 minutes 40 seconds of downtime. The disabled mysql_native_password plugin cost six hours. Notes on the LTS model, the removed options, and the pre-flight query I should have run.
-
Laravel 13 and the first-party AI SDK
Three months on Laravel 13 in our internal ops app: what the AI SDK replaced in our ticket triage code, the numbers we measured, the 0.x release that broke our structured output, and the parts we did not turn on.
-
Symfony 8 on PHP 8.4: the config rewrite nobody warned us about
We went from Symfony 7.4 to 8.0 on PHP 8.4. Most of the work was converting fluent PHP and XML config to array shapes, not chasing removed APIs. Notes on what broke and whether 7.4 is the better call.
-
Laravel 12: the release where almost nothing broke
Our internal ops app went from Laravel 11 to 12 in under an hour of real work. The only genuine breakage was Carbon 3, which quietly flattened a finance report. Notes from three months in.
-
Laravel 11 and the missing Kernel.php
Notes from moving our internal ops app from Laravel 10 to 11: why we kept both kernel files, how per-second rate limiting fixed a courier webhook, and what the /up route is really doing.
-
json_validate and typed class constants, four months in
Measured numbers from validating a 24.7 MiB partner payload with json_validate instead of decoding and discarding it, the one case where it saves nothing, and what typed class constants caught in our code.
-
Symfony 7: the upgrade that took an afternoon, and the one that took a month
We went 6.4 to 7.0 in January. The version bump was an afternoon of deprecation cleanup; converting 704 route annotations to attributes took a month. Notes on both, plus the normalizer that broke in production.
-
Laravel 10 in an internal app: native types, the Process facade, and Pennant
Our internal ops app went 9 to 10 in nine hours, not the ten minutes the upgrade guide estimates. Notes on two silent breaks, replacing exec() with the Process facade, and the Pennant gotcha that bit us.