Product craft

Product is not
the roadmap.

I’m at my best when the customer job is messy, the system is imperfect, and the original plan has stopped being a useful proxy for reality. Product judgment lives in that gap: understand what changed, make the decision, and stay accountable to what happens next.

$10M+ARR portfolio spanning 12+ products
~20%annual Document Management growth during ownership
8–10legacy SIS integrations owned with Engineering
~15engineers + QA across core product teams
What I optimize for

A few rules I actually use.

  1. Own the outcome, not the roadmap.Plans matter until reality gives you better evidence.
  2. Maximize the work not done.Complexity has to earn its way into the product.
  3. Treat the request as evidence, not a requirement.The literal ask is often a clue to the real job.
  4. Put the capability where the work happens.Workflow, distribution, and architecture are often the same product decision.
  5. Done is customer-visible.Merged, released, green, complete, and validated are different states.

Own the outcome, not the roadmap

I stopped the redesign I had fought to fund.

The UX problem was real. Sales wanted the visible improvement. I had spent political capital getting the work onto the roadmap. Then product health became the binding constraint.

Decision

I paused my own redesign, moved Engineering capacity into reliability and performance, and kept responsibility for returning to the original customer problem once the product was healthy enough.

Several core loads were taking more than 30 seconds. Some document jobs took 24+ hours or never completed. The customer, support, and technical backlog had climbed above 1,000. A better interface on top of an unreliable core was no longer the highest-value investment, and pretending we could fully fund both priorities would only make the sequencing less honest.

30+ sec → ~2 secaffected core loads
24+ hr → ~30 minmost long-running jobs; ~1–2 hr max
1,000+ → ~50backlog in roughly 3–4 months

Roughly two quarters later, once the product could support it, we returned to the redesign and delivered the new UI. That loop closure matters to me. “Priorities changed” is not a free pass to forget why the original work mattered.

Boundary: Engineering owned the performance diagnosis and implementation. I owned the product sequencing, capacity decision, stakeholder tradeoff, and the decision to return to the UI work.

Maximize the work not done

Complexity has to earn itself.

One Agile principle I keep coming back to is maximizing the amount of work not done. I don’t read that as “ship less.” I read it as: do not make the customer and the team pay forever for complexity that never earned its way into the product.

Decision

When a bulk uploader stopped being capable of solving the migration-scale job that justified it, I stopped the sunk work rather than redefine success around what we had already built.

The original need was districts moving hundreds or thousands of historical documents. Engineering reality reduced the feasible path to only a few dozen files, while existing workflows already covered smaller jobs. At that point, “we can technically ship this” was not the same as “this is still worth shipping.”

I reframed the problem around a real migration / ETL path. Later discovery surfaced requirements of 1,000+ files and, in one case, a migration around 500,000 documents. That validated the scale mismatch; it does not mean I claim a generalized migration product eventually shipped.

Same instinct · smaller surface

Use the interface you already have before inventing a deeper integration.

For a Naviance-to-SIS workflow, stable public URLs removed a cross-team delivery dependency and provided enough of the customer experience. A deeper selected-student/tokenized path would have added materially more authentication work and coupling for limited incremental value, so I deferred it.

Treat the request as evidence

Ask why the weird request exists.

A customer asked us to support more than 50 students inside an incident-management workflow. The useful signal was not the number. It was that the request made no sense under the intended job.

Decision

Instead of raising the limit, I called the customer to understand why anyone would need an incident with that many students.

They were repurposing the incident feature because it happened to update attendance for participating students. The actual job was bulk attendance, not giant incidents. I brought that job back to the SIS team, and a generalized bulk-attendance capability went into the next sprint.

A strange feature request is often evidence about the user’s real job, not evidence that the requested feature should literally exist.

Commercial version of the same move

Decompose the scary requirement before promising the scary solution.

A Middle East opportunity initially sounded like an emergency full-Arabic / RTL platform requirement. I traced the immediate parent workflow and found Arabic PDFs and email already covered the near-term job; broader UI translation could remain strategic work instead of becoming an artificial emergency commitment.

Put the capability where the work happens

Distribution can be product strategy.

PowerSchool SIS was the largest internal market for Document Management. That made forcing users into a separate destination a product problem, not merely a navigation problem.

Decision

I pushed Document Management from a standalone application toward a shared PowerHub capability and drove the product surface across authentication, micro-frontend UI, and SIS data access.

Standalone destinationshared identityMFE surfaceSIS data accessPowerHub exposure

The interesting decision was not “use a micro-frontend.” It was recognizing that the capability should live closer to where the institutional workflow already happened, while avoiding unnecessary dependence on another team’s delivery cycle. I defined the product surfaces and drove the cross-product/platform work; Engineering and platform teams owned the implementation architecture.

That same pattern ran through roughly 8–10 SIS integrations: start with the customer workflow, define the data and system-of-record dependencies, choose how much integration is actually worth buying, and let Engineering own the technical implementation inside those boundaries.

Boundary: PowerHub exposure shipped. I do not have a defensible adoption metric, so I do not use one.

Done is customer-visible

The organization cannot declare victory for the customer.

My definition of done got stricter over time, partly because I got burned when I trusted internal completion states too much. A green ticket, a release, or an engineer saying “complete” can all be true and still fail to prove that the customer can do the job.

Leading signal · Mobile support

A dashboard was already too late.

I mapped how support issues moved from Salesforce into Jira, built alerting around the qualifying paths, tested the trigger end to end, and kept the dashboard as a backstop. The Mobile board finished the measured period at 100% YTD OLA across 1 P1 and 10 P2 tracked tickets; that was a team outcome, with me owning the product-side mechanism and response discipline.

Target environment · TDSB

Released is not the same as validated.

Report-card work had technically been released, but the customer’s customized ReportWorks environment broke assumptions the standard path relied on. The durable lesson was simple: for consequential enterprise workflows, target-environment verification is part of done.

Internal green · River East

“Complete” is not customer-visible proof.

A migration of roughly 500,000 documents was reported internally as complete; the customer could see about 1,500. A script had failed and the primary engineer was out. We moved into recovery, but I do not claim the final migration outcome because I no longer have clean evidence of it. What changed for me was the standard: consequential completion requires verification at the surface the customer actually uses.

Production tradeoff · SSO P0

Restore correctness, then repair the optimization.

During report-card season, school data missing from the initial SAML-derived state left a school-less current-user response cached for 30 minutes even after a later SIS call found the correct school. Engineering owned the fix; I stayed close enough to the mechanism to help drive the product response: temporarily disable the relevant caching, accept a bounded performance cost, restore the blocked workflow, and communicate the hotfix through resolution.

The operating surface

The stories are where the judgment is easiest to see. The job was wider.

I spent seven years inside institutional software where the customer workflow routinely crossed products, teams, release trains, permissions, integrations, support systems, and commercial commitments.

Enterprise product

Strategy · roadmap · portfolio · lifecycle · discovery · migration · localization · workflow design

Technical product

REST APIs · identity / SSO · MFE · data contracts · permissions · performance · system dependencies

Customer / GTM

RFPs · demos / QBRs · beta testing · Sales enablement · procurement · security / privacy

Operating

Releases · incidents · hotfixes · escalations · Support · readiness · customer communication

I did not own a formal P&L and did not manage the engineers. I was expected to operate like a business owner across product outcomes: make the Product decisions, keep the seams legible, and stay accountable when the system or the customer disagreed with the plan.

2025–present

Building directly changed the resolution, not the job.

Since leaving PowerSchool, I’ve gone materially closer to code, system behavior, evaluation, and verification. That changed how much I can inspect myself and how quickly I can test an idea. It did not change what I think Product is for.

Understand the customer. Understand the system. Make the tradeoff. Stay accountable to what happens next.