Before starting at Hydro One, my mental model of software engineering was entirely shaped by web and cloud work. APIs, databases, CI pipelines. The idea that software could be directly responsible for keeping the lights on across an entire province was abstract at best. A few months in, it is not abstract anymore.
Consumer software fails gracefully. A crashed web app gets a refresh. In protection and control systems, a failed process can mean an undetected fault, a missed alarm, or in the worst case, an uncontrolled fault clearing event. That possibility changes how you think about every line you write.
The stack reflects this. Embedded devices running deterministic firmware, real-time telemetry pipelines, and centralized SCADA systems all need to agree on state at all times. When they don't, the discrepancy has to be caught and diagnosed. Not tolerated.
In most software roles I've seen, testing is something you do after you build. Here, testing is the deliverable. The product of my work is not new features. It's confidence that the system behaves correctly under every condition we can simulate.
You do not ship confidence. You test until doubt is no longer reasonable.
Working in this environment has sharpened instincts that apply everywhere. Writing code that fails loudly instead of silently. Tracing failures across layers instead of assuming the problem is in the most obvious place. Treating test coverage as a first-class concern, not an afterthought.
The constraints of critical systems are a useful lens even when you go back to building apps. The question "what happens when this is wrong?" gets a lot more interesting when you've worked in a domain where the answer actually matters.