1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
//! # The DORA Metrics Framework
//!
//! The **DORA metrics** come from the DevOps Research and Assessment
//! programme, later published as the book *Accelerate*, which surveyed tens
//! of thousands of engineering professionals to find which delivery
//! practices correlate with organizational performance. Four metrics, paired
//! two and two: **deployment frequency** and **lead time for changes**
//! measure speed; **change failure rate** and **failed deployment recovery
//! time** measure stability. The framework's central finding is that elite
//! performers are fast and stable simultaneously — speed and safety do not
//! trade off against each other the way intuition suggests.
//!
//! ## Formula
//!
//! ```text
//! Deployment frequency = deployments / days
//! Lead time for changes = deploy time − first commit time
//! Change failure rate (%) = (failed deployments / total deployments) × 100
//! Failed deployment recovery = restored time − detected time (never the deploy event)
//! ```
//!
//! ## Why it matters
//!
//! DORA measures the pipeline, not the value flowing through it: a team can
//! post excellent DORA numbers while its actual output has quietly drifted
//! toward rework, a gap this book's Flow Framework chapters are built to
//! surface and DORA cannot see. Used within that bounded scope, DORA gives
//! large organizations a consistent, comparable measure of pipeline
//! mechanics across many teams — genuinely valuable for prioritizing
//! platform investment, provided all four metrics are reported together and
//! never applied to individual performance reviews.
//!
//! ## Example
//!
//! A platform team's change failure rate falls from 25% to 8% across 100
//! production deployments a year, a stability improvement that DORA's
//! pairing discipline insists on measuring alongside any speed gain, never
//! in isolation.
//!
//! ```rust
//! use software_engineering::dora_metrics::{
//! change_failure_rate_percent, deployment_frequency_per_day,
//! lead_time_for_changes_hours, failed_deployment_recovery_time_hours,
//! };
//!
//! let cfr_before = change_failure_rate_percent(25.0, 100.0).unwrap();
//! let cfr_after = change_failure_rate_percent(8.0, 100.0).unwrap();
//! assert_eq!(cfr_before, 25.0);
//! assert_eq!(cfr_after, 8.0);
//! assert!(cfr_after < cfr_before);
//!
//! // 2 deployments/day, a 6-hour lead time from first commit to production,
//! // and a 1.5-hour recovery from detection to restoration.
//! assert_eq!(deployment_frequency_per_day(14.0, 7.0).unwrap(), 2.0);
//! assert_eq!(lead_time_for_changes_hours(0.0, 6.0), 6.0);
//! assert_eq!(failed_deployment_recovery_time_hours(10.0, 11.5), 1.5);
//! ```
//!
//! ## Pitfalls
//!
//! - **Treating DORA as the whole picture of delivery health** — it is
//! silent on what kind of value is being delivered; pair it with flow
//! distribution.
//! - **Reporting only the speed half** — defeats the framework's central
//! finding that speed and stability move together in high performers.
//! - **Using DORA metrics in individual performance reviews** — breaks the
//! framework's statistical validity and invites gaming.
//! - **Comparing teams with inconsistent definitions** of "deployment,"
//! "change," or "failure" — produces comparisons that look fair but are
//! not.
//! - **Self-reported DORA numbers instead of pipeline-instrumented ones** —
//! reintroduces exactly the bias the framework was designed to eliminate.
//!
//! ## Sources
//!
//! - Chapter 2.10, The DORA metrics framework.
//! - Forsgren, Nicole, Jez Humble, and Gene Kim, *Accelerate: The Science of
//! Lean Software and DevOps* (2018).
//!
//! Topic doc: software-engineering-metrics/locales/en-001/chapters/02-10-the-dora-metrics-framework.md
/// Change failure rate: the percentage of deployments that caused a failure
/// requiring remediation, a rollback, a hotfix, or an incident.
///
/// `(failed_deployments / total_deployments) × 100`. Definition drift here
/// is the chapter's specific warning: agree on what counts as a "failure" in
/// writing before comparing this number across teams.
///
/// # Arguments
///
/// * `failed_deployments` — count of deployments that caused a failure.
/// * `total_deployments` — total count of deployments in the period.
///
/// # Returns
///
/// The failure rate as a percentage (0.0–100.0 for sane inputs), or `None`
/// if `total_deployments` is zero.
///
/// # Examples
///
/// ```rust
/// use software_engineering::dora_metrics::change_failure_rate_percent;
///
/// assert_eq!(change_failure_rate_percent(25.0, 100.0), Some(25.0));
/// assert_eq!(change_failure_rate_percent(8.0, 100.0), Some(8.0));
/// assert_eq!(change_failure_rate_percent(1.0, 0.0), None);
/// ```
/// Deployment frequency: how often a team successfully releases to
/// production.
///
/// `deployments / days`. Count only successful production deployments,
/// instrumented from the pipeline, never self-reported, and watch for
/// substitution gaming — splitting one meaningful change into several
/// trivial deploys purely to inflate the count.
///
/// # Arguments
///
/// * `deployments` — count of successful production deployments.
/// * `days` — length of the observation period, in days.
///
/// # Returns
///
/// Deployments per day, or `None` if `days` is zero.
///
/// # Examples
///
/// ```rust
/// use software_engineering::dora_metrics::deployment_frequency_per_day;
///
/// // 14 deployments across a week is 2 per day.
/// assert_eq!(deployment_frequency_per_day(14.0, 7.0), Some(2.0));
/// assert_eq!(deployment_frequency_per_day(1.0, 0.0), None);
/// ```
/// Lead time for changes: the time from a code change's first commit to its
/// successful deployment in production.
///
/// `deploy_time_hours − first_commit_time_hours`. Report both the median and
/// a high percentile across many changes, not just a mean, since this
/// quantity is typically skewed.
///
/// # Arguments
///
/// * `first_commit_time_hours` — timestamp of the change's first commit, in
/// hours on any consistent scale.
/// * `deploy_time_hours` — timestamp of its successful production
/// deployment, on the same scale.
///
/// # Returns
///
/// The elapsed lead time in hours.
///
/// # Examples
///
/// ```rust
/// use software_engineering::dora_metrics::lead_time_for_changes_hours;
///
/// // First commit at hour 0, deployed at hour 6: a 6-hour lead time.
/// assert_eq!(lead_time_for_changes_hours(0.0, 6.0), 6.0);
/// ```
/// Failed deployment recovery time (often shortened to MTTR): how long it
/// takes to restore service once a deployment causes a failure.
///
/// `restored_time_hours − detected_time_hours`. Start the clock at
/// detection, not at the deploy event itself, so the number reflects
/// genuine recovery delay rather than a monitoring gap.
///
/// # Arguments
///
/// * `detected_time_hours` — timestamp the failure was detected, in hours on
/// any consistent scale.
/// * `restored_time_hours` — timestamp service was restored, on the same
/// scale.
///
/// # Returns
///
/// The elapsed recovery time in hours.
///
/// # Examples
///
/// ```rust
/// use software_engineering::dora_metrics::failed_deployment_recovery_time_hours;
///
/// // Detected at hour 10, restored at hour 11.5: a 1.5-hour recovery.
/// assert_eq!(failed_deployment_recovery_time_hours(10.0, 11.5), 1.5);
/// ```