I recently shipped an undo/redo system for a client-side app, and it reminded me how deceptively deep this feature goes. What begins as “just keep two stacks” quickly becomes a set of product and engineering decisions: what counts as a single step, how to group multi-part changes, what belongs in history versus “session” UI state, and how to handle cancellations or partial failures without surprising users. In part 1 of this series, I share the mental model and history design rules that make undo/redo predictable and maintainable, plus a quick tour of common approaches (snapshots, commands, patches) and the cloning and boundary pitfalls that break most first attempts. Part 2 builds on that foundation with transactions and rollback.