Wheels 4.1 isn't another "we added features and fixed bugs" release. It's the release where a single bug report sent us back to the drawing board, where a security pass made the things you always assumed were safe actually be safe, and where the framework got meaningfully faster. Here's what's coming, and the story behind it.
Wheels 4.0.6 is the first 4.0 feature release after 4.0.5's hardening pass — one-command authentication (`wheels generate auth`), an authorization policy layer, pluggable local/S3 storage disks, query-builder chains that can start with `select()`, and the mixin-plan cache that was making 4.0.x feel slow. Also: Adobe `onApplicationEnd` teardown, tenant/pagination request-key collisions, test-runner isolation, and a production gate on `/wheels`.
i18n usually arrives as an emergency. wheels-i18n makes the mechanical part boring: t() and tp() with interpolation and pluralization, JSON or database catalogs, session-based locale switching, and the fallback chain that makes incremental translation actually shippable.
Most developers use a fifth of the debug bar and writeDump() around the rest. The full tour: what each panel answers, the developer tools behind the last tab, the throughput cost worth knowing, and why the bar can't follow you to production — by design.
Declare fullName or commentCount once as SQL on the model and it behaves like a column everywhere — sortable, selectable, never stale. And Wheels 4's select=false + includeCalculated pair fixes the cost problem calculated properties always created: expensive expressions run only where they're asked for, additively.
A REPL inside your running app: models resolve, scopes chain, the DI container answers, settings read back. The sessions that replace writeDump-and-refresh archaeology, the slash-commands, and why console and repl are different tools that look alike.
SSE gives you the pipe; channels answer the harder question — how the model callback that knows something happened reaches the connection three requests away. publish(), subscribeToChannel(), channelSSETag(), the memory-vs-database adapter decision, and the named-event gotcha that catches almost everyone.
findAll on 400,000 rows materializes everything into memory at once — and the request cache holds it there. Wheels 4's findEach and findInBatches walk big result sets a page at a time, with three built-in optimizations you'd forget to hand-roll and two sharp edges worth knowing first.
CommandBox teams do not have to switch. The complete box-native workflow for Wheels 4 — install from ForgeBox, engine selection with cfengine, datasources via CFConfig, every framework task's in-app equivalent, CI with setup-commandbox, and an honest accounting of what the wheels CLI adds if you ever want it.
Why exporting WHEELS_ENV=production doesn't flip your app into production — and everything else about the config pipeline: the three-file load order, the .env chain that shadows OS variables, what production mode really changes, and the reload gate's fail-closed mechanics.