Designing with complexity: how I approach messy requirements
Every product I've worked on came with a “wait, what happens if the user does this?” moment. Requirements that sounded clear on paper turned out to have five edge cases buried inside. Stakeholders who wanted different things. Logic that made perfect sense to the business but completely broke the user's mental model.
This is not an exception in product design. It's the rule. And it's actually where the most interesting design work lives.
Start with the messiest case, not the happy path
My instinct when a new project lands is to map the worst-case flow first. What happens when the user has insufficient balance and tries to partially redeem a voucher across two currencies? What does the back office operator see when their permission level doesn't match what the frontend expects?
Designing for those cases first makes the happy path trivial. It also forces every stakeholder to confront the product's actual complexity before a single pixel is placed.
Clarify before you wireframe
The fastest I've ever shipped something wrong was when I skipped straight to wireframes. Requirements felt solid enough. They weren't.
My process now: before opening Figma, I write out every user role, every state, and every combination I can think of. Then I send it back to the PM or stakeholder with one question: “Is there anything here that can't actually happen?”
That question has caught more edge cases than any design review session.
Implementation reality is part of the brief
A design that can't be built isn't a design, it's a sketch. I've gotten much faster at thinking about component states, responsive breakpoints, and API constraints from the start — not as an afterthought once engineering pushes back.
Working closer to code (ReactJS, SCSS, Git, and now AI-assisted implementation workflows) changed how I think about complexity. When you understand what the component tree looks like, you design interaction states that are actually buildable, not just visually plausible.
Complexity is not the enemy
The goal isn't to eliminate complexity. It's to make it invisible to the user while remaining legible to the team building it.
A partial payment flow with three payment methods, two coupon types, and a minimum spend rule will always be complex underneath. What design can do is structure that complexity so users only see what they need at each step, and engineers have a clear spec for every state.
That gap between “what the product actually does” and “what the user needs to think about” — that's where product design lives.