DEV Community

Babar Hayat for OpsVeritas

Posted on

Define Success Before You Ship: The Five-Question Contract

You're shipping an automation tomorrow. The logic is sound. The nodes connect. But here's the question nobody asks before deployment: what does success actually mean for this system?

Most builders skip this step. They ship observing only whether the system ran—logs green, no errors, nodes fired. Then they're blindsided when a workflow executes perfectly and produces zero real consequence. The incident happens not at the execution layer, but at the gap between "the system finished" and "the system actually did what it was supposed to do."

This is the success-contract problem. And it's solvable, cleanly, before you deploy a single line of code.

The gap: execution vs. outcome

Here's the mechanism. A workflow can satisfy its framework contract perfectly—every node succeeds, every API call returns 200, the orchestration completes—while violating its business contract entirely. A hiring workflow screens resumes, assigns panelists, schedules interviews, and logs success at each step. Three days later, the candidate hasn't moved forward because one panelist never actually showed up. The system looks fine. The pipeline is blocked invisibly.

This isn't a framework bug. It's a design gap. The framework was built to orchestrate; it wasn't built to verify that the orchestration actually moved the needle in the real world.

Builders discover this gap reactively—when a customer complains, when a deadline passes, when a downstream team notices the consequence hours or days later. By then, the failure has already cascaded: decisions were made on bad data, schedules slipped, customers waited.

The fix is to move this discovery earlier: before you deploy, not after it breaks.

Five questions to answer first

Define your system's success contract by answering these five questions upfront. Write them down. Then instrument each answer into your observability before launch.

1. What counts as a successful execution?

Not "did the workflow run." Specifically: what real-world state change proves this system did its job?

For a hiring automation: success isn't "the resume was scored." It's "the panelist received the scorecard request AND confirmed they saw it AND actually scored the candidate."

For an AI agent that publishes content: success isn't "the model generated text." It's "the text appeared in the destination, discoverable and correct."

For a payment reconciliation workflow: success isn't "both systems were called." It's "the ledgers now match AND the transaction is recorded in both places."

Each of these sounds obvious in hindsight. Almost none of them are checked by default by the frameworks you're using.

The check: Can you write a single, testable sentence that defines success? If it takes multiple sentences and conjunctions, you haven't isolated the real outcome yet. Dig deeper.

2. What's the silent-failure mode?

A silent failure is a run that reports success but produces zero real consequence. It's the execution layer telling you "I did my job" while the outcome layer screams "nothing happened."

Enumerate them for your system:

  • Resume screening: the workflow scores a resume but the candidate never sees the result (or sees a malformed score).
  • Panelist assignment: the system assigns an interview to a panelist, logs it as success, but the panelist never receives the notification (or receives it but has no context).
  • Payment processing: the workflow completes, both systems return 200, but the payment sits in limbo because one step required manual review and nobody noticed.
  • Report generation: the agent generates a report, saves it to storage, but saves it to the wrong path or with invalid formatting so downstream readers can't parse it.

The pattern: the system completed without error. The real consequence never materialized. Most monitoring misses this because it's watching the execution, not the outcome.

The check: For each step in your workflow, ask: "How could this step report success while producing zero real outcome?" Write down at least one scenario. If you can't think of any, you're not thinking like an adversary to your own system.

3. What are the real-world side effects you must verify?

Once the system runs, it touches the real world. Document those touches:

  • Does it send a notification to a human? Then verify: did the human actually receive it, or did it land in spam? Did they act on it?
  • Does it write to a database? Verify: did it write the correct data? Can downstream systems read it back?
  • Does it trigger another system (Slack, email, a calendar)? Verify: did the downstream system actually change state?
  • Does it make a financial transaction? Verify: did both ledgers update? Is the transaction idempotent (safe to retry)?

Each side effect is a potential silent-failure point. Most builders watch the outbound call; few verify that the consequence actually landed.

The check: Draw a diagram of your system. Mark every arrow that touches something outside the system itself (a human, a database, an external API, a file store). That's your verification surface. You need visibility into all of it.

4. How do you verify each one?

Now, for each side effect, write down the actual check you'll use:

  • Notification received: poll the recipient's inbox? Ask them to confirm? Or for internal systems, check a confirmation bit?
  • Database write: query back within seconds and compare the values? Set up a validator?
  • Downstream action: did Slack receive the message? Poll the Slack workspace for the message ID? Did the calendar entry appear? Query the calendar API?

This is the layer most builders skip entirely. They assume that because their outbound call succeeded, the consequence landed. In complex systems, this assumption is wrong often enough to matter.

Pick checks that are:

  • Reliable: they reflect real state, not hopeful assumptions.
  • Fast: you want to know within minutes, not hours.
  • Specific: they answer a concrete question ("was the scorecard actually submitted?"), not a vague one ("did the round complete?").

The check: Can you write, right now, the code you'd execute to verify each side effect? If not, you're guessing about what success looks like.

5. What's your baseline, and what's an anomaly?

Once you ship and the system starts running, you'll have baseline data. Use it.

A workflow that processes 100 items per run is healthy baseline. A run that processes 2 items might be a legitimate edge case—or it might be a silent failure where the filter broke and fewer items matched. You won't know without a baseline to reference.

A job that takes 30 seconds is healthy. One that takes 90 seconds might be normal under load—or it might signal that a downstream dependency is choking and the system is silently timing out and retrying.

Before you ship, decide: what does normal look like for your system? Volume, latency, error rates, the shape of the output. Then, as it runs, watch for deviations.

The check: Run your system in a staging environment, let it accumulate real data for a week, and look at the distribution of outcomes. Volume, latency, error rates, the shape of outputs. That's your baseline. Anything that moves significantly from it is worth investigating. Call that an anomaly threshold.

Wiring this into observability

Here's the habit: answer these five questions before you write a single line of production code. Document them. Then, as you build, instrument each answer into your monitoring.

You're not waiting for an incident to define success. You're shipping with visibility built in.

This doesn't require a specialized tool—though tools can help. It requires a habit: design the contract first, then design the checks that verify it.

When your system runs, you'll know not just whether it executed, but whether it actually worked.


What success-contract questions have caught you before? Or blindsided a system you ship? The failures usually follow the same pattern once you know what to look for.

Top comments (1)

Collapse
 
innokentyb profile image
Kent Bodrov •

The hiring example also raises a boundary question: which parts of success does the workflow control, and which depend on a human responding? Delivering a scorecard and a panelist completing it are different states. I would make awaiting-human explicit, with a deadline and escalation, rather than either declaring success at delivery or retrying the creation step when someone is simply late. That keeps a valid delivery from becoming a duplicate side effect.