A deployment is not a single event. Code is packaged, made available, introduced to traffic, observed, and either accepted or withdrawn. Treating all of that as one command hides the decisions that matter.
Separate release from rollout
A release makes an artifact eligible for use. A rollout changes which artifact serves work. Keeping those actions distinct lets a team prepare early, compare exactly what will change, and choose a quiet time to introduce it.
Use immutable artifact identifiers. A label such as stable may move; a digest or version should not. Record both the old and new identifiers before traffic changes.
Observe the change you actually made
Choose a small set of signals tied directly to the rollout: request success, latency, saturation, queue depth, and one product-level outcome. A large dashboard can hide the relevant change as effectively as no dashboard.
If this rollout were harmful in only one region or one request class, would the chosen signals reveal it?
Define the stop condition first
A stop condition turns an uncomfortable judgment into an agreed decision. It should name the signal, threshold, duration, and action. “Watch errors” is vague; “pause if the five-minute error ratio exceeds two percent” is actionable.
Make rollback an ordinary operation
Rollback should use the same delivery path as rollout and should not depend on rebuilding an old artifact. Practice it while the system is healthy. If data shape changes are involved, prefer backward-compatible transitions that let old and new versions coexist.
Small deployment checklist
- Identify the exact old and new artifacts.
- Write down the expected observable change.
- Choose rollout stages and a pause between them.
- Define stop and rollback conditions.
- Confirm that the previous artifact is immediately available.
- Record the result after the observation window.
The aim is not zero risk. It is to make risk bounded, visible, and reversible.