Two change records, both approved, both scheduled for Saturday 03:00, both touching the database tier. CAB approved them separately a week apart. Nobody looked at the calendar. The post-mortem is going to be embarrassing. Freshservice has the data to prevent this — what it lacks is the discipline to use it. Here is the configuration that turns the calendar into an actual gate.
Why the default calendar is not enough
Out of the box, the Freshservice change calendar is a visualisation. It shows you changes on a timeline. It does not stop you from scheduling two changes in the same window, nor does it warn you when a change overlaps a maintenance freeze or a sensitive business event. Visualisation without enforcement is a wall calendar.
Three things turn it into a gate:
- Conflict detection logic on change submission.
- Blackout windows enforced by workflow rules.
- A CAB-facing weekly view that highlights overlaps in red.
Defining a conflict
A conflict between two changes is not just time overlap. The rule that holds up under scrutiny:
Two changes conflict if their planned windows overlap AND they share at least one affected configuration item OR one of the affected CIs has a dependency relationship with one of the other change’s affected CIs.
The CI overlap check is direct. The dependency-relationship check requires the CMDB graph to be in usable shape — which is its own project, see freshservice-cmdb for what “usable” looks like.
function detectConflicts(newChange, allChanges, cmdb) {
const overlaps = allChanges.filter(c =>
c.id !== newChange.id &&
c.status !== 'cancelled' &&
windowsOverlap(c.planned_start, c.planned_end, newChange.planned_start, newChange.planned_end)
);
return overlaps.filter(c => {
const directOverlap = c.affected_cis.some(ci => newChange.affected_cis.includes(ci));
const graphOverlap = c.affected_cis.some(ci =>
newChange.affected_cis.some(nci => cmdb.areRelated(ci, nci, { maxDepth: 2 }))
);
return directOverlap || graphOverlap;
});
}
function windowsOverlap(aStart, aEnd, bStart, bEnd) {
return new Date(aStart) < new Date(bEnd) && new Date(bStart) < new Date(aEnd);
}
Run this on every change creation and update. Surface the result as a warning the submitter must acknowledge, and as a blocker if the conflicting change is already CAB-approved.
Blackout windows
Blackout windows are protected times when only emergency changes are allowed. Examples:
- Last 10 days of every quarter (revenue protection).
- Black Friday week (commerce).
- First 3 days of every month (billing run).
- Public holidays with reduced on-call staffing.
In Freshservice, blackouts are typically modelled as a custom object or a recurring calendar entry that a workflow rule consults. Any standard change scheduled inside a blackout window is rejected at submission. Emergency changes can override but require an additional approval step.
{
"workflow": "Change_Blackout_Enforcement",
"trigger": "Change Submitted",
"conditions": [
{ "field": "change_type", "operator": "is", "value": "Standard" },
{ "field": "is_in_blackout_window", "operator": "is", "value": "true" }
],
"actions": [
{
"type": "set_status",
"value": "Rejected"
},
{
"type": "add_note",
"body": "Change conflicts with blackout window {{blackout.name}}. Reschedule or convert to Emergency with executive approval."
},
{
"type": "notify",
"recipient": "{{change.requester}}",
"template": "blackout_rejection"
}
]
}
The is_in_blackout_window is a computed boolean populated by a serverless function that reads the blackout calendar object and compares against the change’s planned window.
CAB-facing weekly view
The standard calendar view shows changes on a grid. CAB needs more — a sortable list grouped by service tier, colour-coded by risk, and with conflict markers visible.
Build a custom dashboard with these columns: change ID, service, planned window, requester, risk, conflict count, conflict IDs. Sort by planned start ascending. Filter by next 14 days. Colour the row red if conflict count > 0, amber if the change touches a tier-1 service, green otherwise.
Most CAB meetings overrun because the meeting is the first time anyone sees the full week’s slate. Give CAB members the dashboard 48 hours ahead and the meeting itself becomes review-and-decide instead of read-and-react.
See freshservice-change-management for the broader CAB workflow this dashboard feeds into.
Standard, normal, emergency: different rules
Three change classes, three different conflict regimes:
- Standard — pre-approved low-risk patterns (cert renewal, log rotation). Conflict detection is a warning, not a blocker. They are short and idempotent.
- Normal — full CAB review. Conflict detection is a hard blocker against any other normal change with overlap. Submitter must reschedule.
- Emergency — incident-driven. Conflict detection still runs, but the result is informational only. The emergency change manager is making a real-time decision and the system should inform, not gate.
Encoding the differential treatment in workflow rules keeps the calendar usable. Treating all changes equally either over-blocks standard ones or under-protects normal ones.
The CMDB dependency depth question
The conflict detection logic walks the CMDB graph. How deep? Depth 1 means “directly related CIs”. Depth 2 catches “shares a parent dependency”. Depth 3 starts catching cousins and produces too many false positives.
Tune empirically. Run the detection on a quarter of historical changes with depth 2 and depth 3 and count false positives — pairs flagged as conflicting where retrospectively they did not actually conflict. If depth 3 produces a flag rate above 25% you are over-warning. Pull it back to 2.
Holiday and on-call awareness
A change scheduled at 02:00 on a public holiday is a different risk than the same change on a Tuesday. Even if the change itself is low-risk, the recovery path is degraded. Add a soft warning rule:
{
"rule": "After_Hours_Risk_Warning",
"trigger": "Change Submitted",
"conditions_any": [
{ "is_public_holiday": true },
{ "planned_start_hour": { "outside": [9, 17] } },
{ "is_weekend": true }
],
"action": {
"type": "warn",
"message": "This change runs outside business hours. Confirm on-call staffing and rollback rehearsal completed."
}
}
Warning, not block. The submitter often has a good reason (low traffic window, regulatory cutover) and you do not want to fight every after-hours change. Surfacing the question is enough.
Audit trail
CAB-rejected and conflict-flagged changes need an audit trail. Every conflict warning, override, and rescheduling event should write to the change’s activity log with the rationale. Six months later when “why did we approve those two together” comes up, the answer is in the log.
Bake the rationale capture into the override action. If a CAB member overrides a conflict warning, they fill a required free-text field. No silent overrides.
Bottom line
Conflict detection is the difference between a calendar and a control. Three pieces: an explicit overlap-plus-CMDB rule, blackout windows enforced by workflow, and a CAB dashboard that surfaces conflicts before the meeting. Tune the CMDB depth to keep false positives manageable, and capture override rationale in writing. The next pair of overlapping Saturday 03:00 changes never makes it to Saturday.