Engineering Case Notes
Decisions that were contested, reversed, or expensive.
Decisions grouped by theme: what was chosen, and what it cost.
How to read these: each note runs the same way: the situation, what had to be done, what was done, and how it turned out. A note marked Type 1 would have needed a rewrite to reverse. Type 2 was cheap to change later.
What these cover
T
Technical trade-offs
Calls that closed off other options, and what they cost later.
ICEFaces Framework Lock-In
Situation
EIMET's BCMM and ERMM modules needed a JSF component framework. ICEFaces was selected for its AJAX push and its component library, and the JSP layer was built on top of it.
Task
Build a rich UI for government users on a component framework that would not become a dead end.
Action
I built 26 custom tag components against ICEFaces internals (component lifecycle, AJAX bridge, rendering pipeline) across the JSP layer, treating the framework choice as reversible. When ICEFaces stopped being maintained I costed the migration and found the coupling ran through every one of them.
Result
I now ask one question before adopting a dependency: if this dies in three years, what does the migration cost? That drove standard Spring Boot over proprietary alternatives on the next generation.
26 ICEFaces tag components
EIMETType 1: one-way door
1 / 2
L
Learning and accountability
Things that went wrong, and what changed afterwards.
EJB Deployment Coupling
Situation
Legacy EIMET 1.0 ran as two applications over two databases: SIRMM, and BCMM/ERMM. The BCMM/ERMM application reached SIRMM through an EJB client bound to SIRMM's session beans.
Task
Keep two coupled applications shipping when a change to one forced a redeploy of both.
Action
I traced the coupling: the session beans were a compile-time dependency of the client application, so any signature change forced a simultaneous rebuild and redeploy of both. I documented the blast radius and scoped what a network boundary would have cost instead.
Result
Since then I default to a network boundary between separately deployable applications, and treat a shared compile-time contract as a decision that needs justifying rather than the default.
EIMET
1 / 3
F
Feedback and communication
Explaining technical debt and delivery risk to people who do not read code.
Inheriting a Codebase Post-Burnout
Situation
I joined EIMET as a lead developer in late 2022. SIRMM v2, a multi-year Spring Boot rewrite of a legacy monolith, had been carried almost entirely by one developer who burned out and moved off it. A second developer could not close the gap. The MVP date had slipped and management had warned that development could be paused.
Task
Establish how bad it actually was, say so without causing a panic, and put a credible path in front of the steering committee.
Action
My first weeks went to cataloguing the debt and mapping actual state against the charter. I took it to management as delivery risk rather than blame, and recommended scrapping three in-progress initiatives (the schema redesign, the admin rewrite, the encrypted-email feature) to contain scope. The table consolidation moved to v3. Sprint cadence halved to two weeks, and the build moved from Ant to Maven behind a CI pipeline.
Result
The work was re-chartered in June 2024 as a standalone SIRMM 2.0 delivery and passed its Commitment Gate. v2 shipped to production in March 2025 through a three-phase pilot ending agency-wide, recovering a nine-month slip.
9-month slip recovered
SIRMM v2
1 / 2
A
Working with ambiguity
Building where there was no specification to work from, and how the gaps were closed.
Access-to-Web Migration with No Spec
Situation
ECSTP is the ESMD CRA SSC Tracking Portal. Staff drive requests for IT equipment, solutions and services from Shared Services Canada on behalf of internal CRA clients. It had run for years as a Microsoft Access application, with the working rules living in the forms and queries rather than in any written specification; the running application was the only spec there was.
Task
Move it to a web application without losing a business rule nobody had written down.
Action
I read the Access application form by form and query by query, mapping event handlers, validation and lookup queries into a domain model, validating each rule with the people who ran it. Process steps became an EventInstance hierarchy: JOINED inheritance, 21 subtypes keyed to ESMD's procurement catalogue, with the step graph stored per request rather than in a template.
Result
The web application reproduced the Access workflows and added what the desktop version could not do: concurrent access, SPNEGO/Kerberos single sign-on, and a revision history at the JPA level. Rules discovered late, once stakeholders had a working system in front of them, went in as reference-data and event configuration rather than schema changes.
84 entities241 Angular components21 event subtypes
ECSTP
1 / 3
AI
AI in the workflow
Where agents are allowed to lead, and where they are not.
Set out in full on AI-Assisted Work.
Orchestrating Subagents from Workflow Scripts
Situation
On personal projects (this site, the home lab, a self-hosted finance app) a single long agent session drifts. Context fills, earlier constraints fall out, and the output stops matching what was asked.
Task
Get useful work out of coding agents without supervising every step or trusting one long conversation.
Action
I drive agents from deterministic Workflow scripts instead of chat. The script owns the control flow: fan out one stage across files, pipe the results into a review stage, run an adversarial verification pass, then a judge stage that reconciles the outputs. Each subagent is defined separately with its own model, reasoning effort and tool allowlist, and returns structured output so the next stage parses rather than reads.
Result
On this site, agents generated section scaffolding and SVG diagram markup from a data file I wrote, while the case-study content and every architectural claim stayed mine. On the home lab, agents drafted Docker Compose stacks and backup scripts while I configured OIDC, SSL termination and network segmentation by hand.
Portfolio / HomeLabType 2: two-way door
1 / 2
C
Disagreement
Pushing back on a technical direction, and committing once it is decided.
Scrapping a Parallel Schema Redesign
Situation
SIRMM v2 was already behind schedule and a separate schema redesign was running alongside it. Textbook normalization: roughly 120 options tables, one per dropdown, each with identical columns and its own entity, repository and DTO, plus seven email-template tables with no application code behind them.
Task
Decide whether to adopt the redesign or tell the people who funded it that it was not usable.
Action
I mapped the proposed schema against the queries we actually ran. Any incident query touching subtypes would have taken a 20-way left join under JOINED inheritance. The 120 identical options tables meant 120 services and DTOs where two tables would do. I put it to everyone at once as a scope and timing problem rather than a quality one, and committed to doing the consolidation properly in v3.
Result
The redesign was scrapped and v2 shipped. I designed the v3 schema myself: the options tables collapsed into reference_category and reference_option, person data consolidated from 44 tables into 4 generic tables, and @MapsId extension tables replacing the 20-way JOINED inheritance.
120 tables → 244 tables → 4308 → 61 total
SIRMM v2
1 / 2