Engineering Management ·

Engineering OKRs That Drive Results: Setting Technical Goals, Measuring Impact, and Avoiding Vanity Metrics

Most engineering OKRs measure activity instead of outcomes. This guide covers how to write measurable technical objectives, align them with business goals, and run a review cadence that actually works.

Engineering OKRs That Drive Results: Setting Technical Goals, Measuring Impact, and Avoiding Vanity Metrics

Most engineering OKRs fail silently. The team ships them at the end of the quarter, marks everything green, and nothing actually changed for users or the business. The reason is almost always the same: the OKRs measured activity instead of outcomes.

“Completed 47 story points” tells you the team was busy. It says nothing about whether the product got faster, more reliable, or easier to operate. “Merged 120 PRs” tells you the team made commits. It says nothing about whether those commits improved anything. These are vanity metrics with a goal-setting format applied on top.

Engineering OKRs have a structural problem that product OKRs do not. Product teams can point at user metrics: activation rate, retention, conversion. Engineering teams often own work that sits between the system and the user, which makes the connection to outcomes feel indirect. That indirection is not a reason to fall back on activity metrics. It is a reason to think harder about what you are actually trying to change.

Why Engineering OKRs Are Different From Product OKRs

Product OKRs map naturally to user behavior because product changes are visible to users. Engineering OKRs cover system properties that users experience indirectly: reliability, performance, deployment safety, developer productivity.

This creates two failure modes. The first is ignoring the engineering layer entirely and forcing engineering teams to adopt product metrics they do not control. A database team cannot own “user activation rate.” The second failure mode is retreating to pure activity metrics because the outcome is hard to measure. Neither approach works.

The right framing for engineering OKRs is: what system property are you changing, and what is the measurable signal that the property actually changed?

System properties that matter:

  • Reliability: the rate at which the system fails and how quickly it recovers
  • Performance: latency at specific percentiles for specific operations
  • Developer experience: how long it takes engineers to go from idea to production
  • Security posture: the exposure surface and the time to detect and resolve incidents
  • Operational efficiency: how much infrastructure cost it takes to serve a unit of load

Each of these has concrete, measurable signals. None of them require activity counts.

A Framework for Writing Measurable Technical Objectives

An OKR has two parts: the objective (what you want to change) and the key results (how you know you changed it). Engineering teams usually write the objective well and then collapse the key results into task lists.

A key result must be:

  1. Measurable: a number you can pull from a system, not a judgment call
  2. Outcome-oriented: reflects the state of the world, not the work done to get there
  3. Attributable: the team’s actions can plausibly move this number

Here is a TypeScript type that captures what a well-formed engineering key result looks like:

type KeyResult = {
  description: string;
  baseline: number;     // current measured value
  target: number;       // what "success" looks like
  unit: string;         // p99 latency in ms, incidents per month, etc.
  dataSource: string;   // where this number comes from — no judgment calls
  cadence: "weekly" | "bi-weekly" | "monthly";
};

type EngineeringOKR = {
  objective: string;    // qualitative direction: "make the API reliable enough to trust"
  quarter: string;
  owner: string;
  keyResults: KeyResult[];
};

// Example
const reliabilityOKR: EngineeringOKR = {
  objective: "Reduce unplanned downtime to the point where on-call is not a burnout risk",
  quarter: "Q2 2026",
  owner: "Platform team",
  keyResults: [
    {
      description: "Reduce P1 incident count",
      baseline: 8,
      target: 2,
      unit: "incidents per month",
      dataSource: "PagerDuty incident log, severity P1 filter",
      cadence: "monthly",
    },
    {
      description: "Reduce mean time to resolution for P1 incidents",
      baseline: 94,
      target: 30,
      unit: "minutes",
      dataSource: "PagerDuty MTTR report",
      cadence: "monthly",
    },
    {
      description: "Reduce on-call pages during sleeping hours",
      baseline: 12,
      target: 3,
      unit: "pages per engineer per month between 10pm-7am",
      dataSource: "PagerDuty schedule + escalation log",
      cadence: "monthly",
    },
  ],
};

The dataSource field is non-negotiable. If your key result can only be measured by asking someone to manually count things or by inspecting Jira, it will not get measured consistently. If it lives in a dashboard query or a CLI command, it will.

Good vs Bad OKR Patterns

The distinction between a well-formed engineering OKR and a vanity OKR usually comes down to one question: does this number change when the system gets better, or does it change when the team is busy?

PatternBad OKR (activity)Good OKR (outcome)
Reliability”Complete 15 runbook updates""Reduce MTTR for P1 incidents from 94m to 30m”
Performance”Profile 8 slow endpoints""Reduce API p99 latency from 2,100ms to 400ms for the /search endpoint”
Developer experience”Migrate CI to new runner fleet""Reduce median CI build time from 18 minutes to 6 minutes”
Security”Conduct quarterly security review""Reduce mean time to patch critical CVEs from 21 days to 3 days”
Infrastructure”Right-size 30 EC2 instances""Reduce monthly compute spend per 1,000 active users from $420 to $180”
Developer onboarding”Update onboarding docs""Reduce time for a new engineer to merge their first production change from 9 days to 3 days”
Deployment safety”Add 20 integration tests""Reduce production rollbacks from 4 per month to 0 for the checkout service”

Every “bad” OKR in this table has a team somewhere that would mark it green at end of quarter. The “good” version requires the system to actually be different.

OKR Examples by Domain

Reliability

Reliability OKRs should target specific, named services or behaviors. “Improve system reliability” is not an objective. “Make the payment processing path reliable enough that on-call engineers sleep through the night” is.

ObjectiveKey ResultBaselineTargetSource
Eliminate cascading failures in the order pipelineP1 incident rate for order service6/month1/monthPagerDuty
Eliminate cascading failures in the order pipelineMean time to recovery for order service outages47 min12 minPagerDuty MTTR
Eliminate cascading failures in the order pipelinePercent of incidents with automated rollback10%80%Deployment log

Developer Experience

Developer experience OKRs are among the most impactful and most frequently written badly. “Improve developer experience” means nothing. “Reduce the time a developer spends waiting between writing code and seeing it run in staging” is measurable.

ObjectiveKey ResultBaselineTargetSource
Make the development loop fast enough to not interrupt flow stateMedian CI build time18 min5 minCI dashboard
Make the development loop fast enough to not interrupt flow stateMedian time from PR open to first review26 hours4 hoursGitHub API
Make the development loop fast enough to not interrupt flow stateNew engineer time-to-first-production-deploy9 days2 daysOnboarding tracker

Infrastructure and Cost

Infrastructure OKRs should express efficiency in terms of cost per unit of business value, not total cost reduction. Cutting costs by 30% while cutting capacity by 30% is not an achievement.

ObjectiveKey ResultBaselineTargetSource
Reduce infrastructure cost without reducing capacity headroomCost per 1,000 API requests$0.84$0.30CloudWatch + billing
Reduce infrastructure cost without reducing capacity headroomP99 latency under 2x peak load3,400ms800msLoad test results
Reduce infrastructure cost without reducing capacity headroomReserved instance coverage22%70%AWS Cost Explorer

Security

Security OKRs fail most often when they measure compliance activity instead of actual exposure. “Completed SOC 2 Type II audit” is a milestone, not a key result for a security OKR. The actual improvements are in exposure reduction and response time.

ObjectiveKey ResultBaselineTargetSource
Reduce the window between vulnerability disclosure and patchMean time to patch critical CVEs21 days3 daysCVE tracker
Reduce the window between vulnerability disclosure and patchPercent of services with automated dependency scanning14%100%CI config audit
Reduce the window between vulnerability disclosure and patchOpen critical vulnerabilities in production310Snyk dashboard

Aligning Engineering OKRs With Business Goals

The most common complaint from engineering teams about OKRs is that leadership imposes business metrics (revenue, churn, conversion) and then expects engineering to own them, despite the fact that engineering cannot control those metrics directly. This is a legitimate complaint, but the solution is not to disconnect engineering OKRs from the business. It is to make the causal chain explicit.

The structure that works:

  1. Business goal: “Reduce churn by improving product reliability.”
  2. Engineering hypothesis: “If we reduce P1 incidents from 8 to 2 per month, support ticket volume will drop and NPS will improve.”
  3. Engineering OKR: “Reduce P1 incident rate for the core product from 8 to 2 incidents/month.”

This structure lets engineering own what it can actually move, while making the connection to the business outcome visible. It also creates a feedback loop: if you hit the engineering OKR but the business metric does not move, the hypothesis was wrong, which is useful information.

The TypeScript representation of this alignment:

type BusinessAlignment = {
  businessGoal: string;
  hypothesis: string;  // if we do X, then business metric Y will improve because...
  engineeringOKR: EngineeringOKR;
  leadingIndicator: string;  // what engineering measures; often daily/weekly
  laggingIndicator: string;  // what business measures; often monthly/quarterly
};

const alignedOKR: BusinessAlignment = {
  businessGoal: "Reduce churn driven by reliability perception",
  hypothesis:
    "If P1 incident rate drops below 2/month and MTTR drops below 30 min, " +
    "support escalation volume drops, which reduces churn in the enterprise cohort",
  engineeringOKR: reliabilityOKR,
  leadingIndicator: "P1 incident count and MTTR (PagerDuty, weekly)",
  laggingIndicator: "Enterprise cohort 90-day churn rate (CRM, monthly)",
};

The leading/lagging indicator split is how you avoid two failure modes: engineering claiming credit for business outcomes they did not cause, and business stakeholders dismissing engineering work because the P&L has not moved in the six weeks since you shipped.

Cadence and Review Processes That Work

OKRs need a review cadence that surfaces problems early enough to change course. A quarterly OKR with no mid-quarter check-in is a post-mortem format, not a management tool.

A cadence that works for engineering teams:

Weekly (15 minutes, async): Update the current values for each key result in a shared doc or dashboard. Flag blockers. No discussion unless something is moving in the wrong direction.

Bi-weekly (30 minutes, synchronous): Review current values vs target trajectory. For each key result that is off-track, identify whether the cause is execution (we did not do the work), hypothesis (the work we did does not move the metric), or measurement (we are measuring the wrong thing). Assign an owner to address it.

End of quarter (60 minutes): Score each key result honestly. 0.7 is a good score. 1.0 means the target was too easy. 0.3 means something went wrong. Write the retrospective before you start planning next quarter.

The key discipline is the bi-weekly block. It is where you catch the difference between “we are behind on the work” and “the work we are doing is not actually moving the metric.” The second failure mode is far more dangerous and far more common.

type OKRCheckIn = {
  date: string;
  keyResultId: string;
  currentValue: number;
  targetTrajectory: number;  // where should we be by now given a linear path to target
  status: "on-track" | "at-risk" | "blocked";
  failureMode?: "execution" | "hypothesis" | "measurement";
  blockerDescription?: string;
  ownerAction?: string;
};

Tracking failure mode is important. If you mark a key result “at-risk” every week without distinguishing whether it is an execution problem or a hypothesis problem, you cannot fix it.

Common Anti-Patterns

Sandbagging

Setting targets low enough to guarantee a 1.0 score. This usually comes from a performance review culture where OKR scores matter for promotion. The fix is not to punish teams for 0.7 scores but to explicitly model what a 1.0 score means: the target was too easy.

If your team scores 1.0 on every key result every quarter, your targets are too conservative. An organization where every team consistently scores 1.0 is not a high-performing organization. It is an organization that has learned to game its OKRs.

OKRs as task lists

“Complete API documentation for 12 services” is a task. “Reduce time engineers spend looking for undocumented API behavior from 2 hours/week to 15 minutes/week” is a key result. The difference is not cosmetic. Task lists measure whether work was done. Key results measure whether the work mattered.

The test: can you complete every item on the list and still have the underlying problem get worse? If yes, it is a task list, not a key result.

Vanity metrics

A vanity metric moves in the right direction regardless of whether the system is actually improving. PR count is a vanity metric because merging more PRs does not mean faster feature delivery. Uptime percentage is a vanity metric when you are already at 99.9% because the marginal difference between 99.91% and 99.95% is invisible to users but easy to claim as progress.

Vanity metricWhat it actually measuresBetter alternative
Story points completedTeam was busyFeature delivery cycle time (PR to production)
PRs mergedCommits madeDeployment frequency with rollback rate
Uptime percentage (at 99.9%+)No major outagesMTTR and P1 incident rate
Test coverage percentageTests existDefect escape rate to production
Tickets closedWork was categorized as doneBug count in production over time
Lines of code writtenTeam typed a lotN/A — this is never useful

Misaligned granularity

A team of five engineers with an OKR that is actually a company-level objective will score themselves green because they did their part, while the business outcome they were supposed to drive did not move. The inverse is also common: an individual engineer’s key result rolled up to a team OKR, obscuring whether the team actually improved.

The right granularity is: team-owned OKRs that the team can actually move, with explicit alignment to the next level up (business unit or company objective) documented as a hypothesis, not as a shared metric.

What Good Looks Like at Quarter End

A well-run engineering OKR quarter ends with:

  • Two or three key results that scored between 0.6 and 0.8 (meaningful progress, realistic targets)
  • At least one key result where you learned the hypothesis was wrong and can explain why
  • A retrospective that tells the next quarter’s planning what to prioritize differently
  • Data you can show anyone in the company without needing to explain what “story points” means

The goal is not a perfect score. The goal is a system where engineering work is legible to the rest of the organization, where the team knows whether it is actually improving what it set out to improve, and where the failures are informative rather than hidden.

Engineering that cannot measure its own outcomes is engineering that cannot argue for its own investment. Getting the OKR format right is not bureaucratic overhead. It is how you build the organizational evidence that the work matters.

More in Engineering Management

The AI Productivity Paradox: Why Your Team Ships More Code but Delivers Less
Engineering Management ·

The AI Productivity Paradox: Why Your Team Ships More Code but Delivers Less

AI coding tools create an illusion of velocity at the individual level while degrading team-level delivery, quality, and maintainability. The core mechanism is a 5x+ senior/junior productivity split that aggregate metrics hide entirely.

The AI Productivity Paradox: Why Your Team Ships More Code but Delivers Less Value
Engineering Management ·

The AI Productivity Paradox: Why Your Team Ships More Code but Delivers Less Value

93% of developers use AI coding tools, yet DORA metrics haven't improved proportionally. Individual output rises while bug rates, review times, and deployment instability climb. Here is why individual AI productivity gains create organizational drag, and how to fix it with architecture-level guardrails.

Why Your Engineering Team Is Shipping Slower Than 6 Months Ago
Engineering Management ·

Why Your Engineering Team Is Shipping Slower Than 6 Months Ago

Engineering velocity declines at seed-to-Series-A startups for predictable, diagnosable reasons. Process debt, unclear ownership, hiring mistakes, burnout, and architectural bottlenecks all compound. Here is a diagnostic framework you can run in one afternoon, plus a tradeoffs table for each intervention.

The AI Ratchet Effect: Why Giving Your Engineering Team AI Tools Made Them Work Harder, Not Smarter
Engineering Management ·

The AI Ratchet Effect: Why Giving Your Engineering Team AI Tools Made Them Work Harder, Not Smarter

67% of engineers who adopted AI tools in 2025 worked more hours by year-end, not fewer. This is the AI ratchet effect: management converts every productivity gain into a permanently higher baseline. Here is how it happens, why it is worse at startups, and what a sustainable AI adoption cadence actually looks like.