All posts

code-freeze

Code Freeze Policy Template (With Examples)

A copy-paste code freeze policy template covering scope, schedule, enforcement, overrides, roles, and audit, plus a filled-in example you can adapt today.

Cody Flynn··8 min read

A code freeze policy is a short written document that states which systems stop changing, when, who can approve an exception, and how the freeze is enforced. A good one fits on a page and answers every question an engineer would ask at 2am during an incident: is this repo frozen, does my fix count as an emergency, and who signs off. This post gives you a copy-paste code freeze policy template, explains what each section is for, and shows a filled-in example you can adapt.

The reason to write the policy down is not bureaucracy. It is that an unwritten freeze is enforced by memory and Slack, and both fail under pressure. A written policy turns "we probably shouldn't deploy this week" into a rule with a scope, an end date, and an override path.

What should a code freeze policy include?

A complete code freeze policy answers eight questions. If your document covers these, it is done. If it is missing two or three, that is where the freeze will break down.

SectionThe question it answers
PurposeWhy does this freeze exist and what risk is it protecting against?
ScopeWhich repos, branches, and environments are frozen, and which are not?
ScheduleWhen does the freeze start and end, in a named time zone?
EnforcementHow is the freeze actually blocked, technically?
ExceptionsWhat qualifies as an emergency, and what does not?
Override processWho requests, who approves, and how is it recorded?
RolesWho owns the freeze and who are the named approvers?
Audit and reviewWhere is the log, and when do we review what happened?

Notice what is not on the list: a long justification of why freezes matter, a history of past incidents, or aspirational language about quality culture. Keep those out of the policy. The policy is an operational reference, not an essay.

The code freeze policy template

Copy this, fill in the bracketed fields, and delete the guidance in parentheses. It is written to be adapted, not adopted verbatim.

CODE FREEZE POLICY — [Team or Org name]

1. PURPOSE
This policy governs code freezes for [team/org]. A code freeze is a
defined window during which changes to the systems listed in Scope are
blocked, to reduce the risk of an incident when the cost of failure is
high and response capacity is low.

2. SCOPE
Frozen repositories: [list, or "all customer-facing services"]
Frozen branches: main and release/* (feature branches unaffected)
Frozen environments: production [and staging if it auto-promotes]
NOT frozen: [internal tools, docs, low-risk services — name them]

3. SCHEDULE
Start: [YYYY-MM-DD HH:MM] [TZ, e.g. America/New_York]
End:   [YYYY-MM-DD HH:MM] [TZ]
Recurring: [none | e.g. "every Friday 15:00 to Monday 09:00 ET"]

4. ENFORCEMENT
Merges are blocked by a required status check on frozen branches.
Deployments to frozen environments are blocked by deployment
protection rules. Enforcement is automatic; a Slack announcement is
not the control.

5. EXCEPTIONS (what qualifies as an emergency)
An override is permitted only for:
  - A fix for an active production incident (Sev1/Sev2), or
  - A security patch for an exploited or imminent vulnerability, or
  - A change that unblocks the incident response itself.
Feature work, non-urgent bug fixes, and "it's basically done" changes
do NOT qualify. When in doubt, it does not qualify.

6. OVERRIDE PROCESS
  a. The requester states the reason and the linked incident/ticket.
  b. A second authorized approver (see Roles) must approve. No
     self-approval.
  c. The override applies to that single change only. The freeze stays
     active for everyone else.
  d. The request, approval, requester, approver, and timestamp are
     logged automatically.

7. ROLES
Freeze owner: [name/role] — declares, schedules, and lifts the freeze.
Approvers (any one may approve an override): [names/roles, min. 2].
Escalation if no approver is reachable: [on-call lead / EM].

8. AUDIT AND REVIEW
All overrides are recorded in [audit log location]. Within [5] business
days of each freeze, the freeze owner reviews what shipped under
override and whether scope and duration were correct.

That is the whole policy. Around 40 lines. If yours runs to three pages, it has drifted from policy into procedure documentation, and nobody will read it during an incident.

A filled-in example

Here is the same template completed for a payments team running a holiday freeze. Use it as a reference for the level of specificity to aim for.

CODE FREEZE POLICY — Payments Platform

1. PURPOSE
Reduce incident risk on payment-critical services during the December
holiday period, when transaction volume peaks and on-call coverage is
thin.

2. SCOPE
Frozen repositories: payments-api, ledger, checkout-web, fraud-service
Frozen branches: main, release/*
Frozen environments: production
NOT frozen: payments-docs, internal-admin-tools, load-test-harness

3. SCHEDULE
Start: 2026-12-19 17:00 America/New_York
End:   2027-01-02 09:00 America/New_York
Recurring: none (one-time seasonal freeze)

4. ENFORCEMENT
Required status check "freeze/payments" on frozen branches; GitHub
deployment protection rule on the production environment. Both managed
by NoShip. Automatic, not announcement-based.

5. EXCEPTIONS
Override permitted only for Sev1/Sev2 production incident fixes,
actively exploited security patches, or changes that unblock incident
response. No feature work.

6. OVERRIDE PROCESS
Requester posts reason + incident link in #payments-freeze. On-call
lead or release manager approves (not the requester). Override is
per-change. All actions auto-logged.

7. ROLES
Freeze owner: Release Manager (Dana R.)
Approvers: On-call lead (rotation), Release Manager, Eng Director
Escalation: Eng Director if no approver responds within 30 minutes.

8. AUDIT AND REVIEW
Overrides logged in NoShip audit trail. Post-freeze review on
2027-01-05.

Two things make this example work. The scope names the four repositories that actually process money and explicitly excludes the docs and admin tools, so nobody freezes work that carries no holiday risk. And the exceptions section draws a hard line: incident fixes and security patches get through, feature work does not. That single distinction prevents most of the "is this urgent enough" arguments a freeze otherwise generates.

How do you enforce the policy, not just publish it?

A policy document does not stop a merge. Enforcement is a separate, technical step, and it is where most freezes actually fail. A policy that says "production is frozen" while the merge button still works is a suggestion.

There are two enforcement points on GitHub, and a real freeze uses both:

  • Blocking merges. A required status check on the frozen branches must post a failure status to every open pull request while the freeze is active, and success when it lifts. New PRs opened mid-freeze need the check applied at creation time, which requires a webhook listener rather than a one-time script. The how to block merges to main post covers the mechanics.
  • Blocking deployments. Merges and deploys are different events. A change already merged before the freeze can still deploy unless you also gate the environment. GitHub deployment protection rules cover that path.

The override section of your policy is only meaningful if enforcement is automatic. If any engineer can merge past a Slack warning, the dual-approval process in section 6 is theater. Automated enforcement is what gives the exception process teeth. The code freeze best practices post goes deeper on why announced freezes do not hold at scale.

Common mistakes to avoid

Most broken freeze policies fail in one of a few predictable ways.

  • "Until further notice" for the end date. A freeze without a defined end drifts, held-back work piles up, and the thaw becomes its own incident. Always set an end timestamp, even if you extend it later.
  • Freezing everything to be safe. A blanket org-wide freeze stops low-risk teams from shipping for no reason and teaches engineers to treat freezes as bureaucracy. Scope to the systems that carry the actual risk.
  • No definition of "emergency." If the policy does not say what qualifies, every held-back change becomes an emergency by 4pm. Section 5 has to draw the line explicitly.
  • Self-approved overrides. An override one person can grant themselves is not a control. Require a second authorized approver, always.
  • No audit trail. If you cannot answer "what shipped under override during the freeze" afterward, you cannot review whether the freeze worked or tighten it next time.

Where NoShip fits

The template above is the policy. Turning it into something that enforces itself, on schedule, without a person managing each step, is the tooling question.

NoShip is a GitHub App that implements this policy directly: required status checks across every connected repository, RRULE-based schedules for recurring freeze windows, rule-based scoping by repo and environment, dual-approval emergency overrides, and a signed audit trail that answers the section-8 review questions automatically. It requests no access to your source code. The concepts guide shows how freeze windows, rules, and overrides map to the sections of the template.

Write the policy first. It forces the decisions (scope, schedule, who approves) that no tool can make for you. Then pick how much of the enforcement you want to build yourself versus run off the shelf.

Keep reading