Why the MilestoneType Metadata Type Matters
Before you can build an EntitlementProcess in Service Cloud, you must define the reusable milestone building blocks using MilestoneType (milestoneTypes/<Name>.milestoneType-meta.xml). Each MilestoneType represents a contractual checkpoint—such as First Response, 4-Hour Status Update, Workaround Provided, or Final Resolution—and dictates whether that checkpoint fires once or repeats throughout the lifecycle of a Case or Work Order.
Key Metadata Fields & The Recurrence Naming Inversion
| Field | Type | Required | Description |
|---|---|---|---|
description |
string |
No | Documents when and how this milestone should be completed. |
recurrenceType |
MilestoneTypeRecurrenceType |
No | Controls whether the milestone occurs once or repeats. Valid values: none, recursIndependently, recursChained. |
Warning
Critical Metadata API Naming Inversion (recursIndependently vs. recursChained): In the Salesforce Metadata API and SOQL schema, the enum names are inverted relative to the Setup UI labels:
none= No Recurrence (occurs only once on the Case, e.g., First Response or Resolution Time).recursIndependently= Sequential in the Setup UI (the next occurrence’s start time is set only after the current occurrence is marked completed).recursChained= Independent in the Setup UI (the next occurrence’s start time is chained to the target date of the previous occurrence regardless of when the agent completed it).
Real-World XML Examples
1. Non-Recurring Milestone (milestoneTypes/First Response.milestoneType-meta.xml)
<?xml version="1.0" encoding="UTF-8"?>
<MilestoneType xmlns="http://soap.sforce.com/2006/04/metadata">
<description>Initial human response sent to the customer acknowledging the support request.</description>
<recurrenceType>none</recurrenceType>
</MilestoneType>2. Sequential Recurring Milestone (milestoneTypes/Executive Status Update.milestoneType-meta.xml)
<?xml version="1.0" encoding="UTF-8"?>
<MilestoneType xmlns="http://soap.sforce.com/2006/04/metadata">
<description>Periodic status update required every 2 hours while a Critical P1 incident remains open.</description>
<recurrenceType>recursIndependently</recurrenceType>
</MilestoneType>Querying MilestoneType and CaseMilestone with SOQL
Both MilestoneType (the metadata definition) and CaseMilestone (the runtime SLA tracker on a Case) are queryable in standard SOQL. This is essential for writing Apex triggers or Record-Triggered Flows that automatically set CaseMilestone.CompletionDate = System.now() when an agent sends an email or closes a Case.
1. List All Milestone Types Configured in the Org
SELECT Id, Name, Description, RecurrenceType, LastModifiedDate
FROM MilestoneType
ORDER BY Name ASC2. Query Open or Violated Case Milestones for Auto-Completion in Apex/Flow
SELECT Id, CaseId, Case.CaseNumber, MilestoneType.Name,
StartDate, TargetDate, CompletionDate,
IsCompleted, IsViolated, TimeRemainingInMins, ElapsedTimeInMins
FROM CaseMilestone
WHERE CaseId = :targetCaseId
AND IsCompleted = false
AND MilestoneType.Name = 'First Response'Senior Architect Best Practices
- Automate
CaseMilestone.CompletionDatevia Record-Triggered Flow orEmailMessageTrigger: Agents should never have to manually click “Mark Completed” on the Milestone Tracker component. Use an after-insert Flow onEmailMessage(whereIncoming = false) to query openFirst ResponseandExecutive Status UpdateCaseMilestonerows and setCompletionDate = System.now(). - Keep
MilestoneTypeNames Concise: BecauseMilestoneTypefile names in SFDX (milestoneTypes/First Response.milestoneType-meta.xml) preserve spaces and match the exact UI label, avoid punctuation or trailing spaces that complicate CLI scripts.
Frequently asked questions
What are the three recurrenceType options on MilestoneType?
The recurrenceType field supports none (No Recurrence, such as First Response or Final Resolution), recursIndependently (Sequential recurrence where the next milestone starts only after the previous one completes), and recursChained (Independent recurrence at fixed intervals).
Why does Salesforce name Sequential recurrence recursIndependently and Independent recurrence recursChained in the Metadata API?
This is a well-known historical naming inversion in the Metadata API schema: recursIndependently maps to Sequential in the Setup UI (starts when the previous instance completes), whereas recursChained maps to Independent in the Setup UI (starts based on the initial trigger time).
Can you change the recurrenceType of an existing MilestoneType once it is used in an EntitlementProcess?
No. Once a MilestoneType is referenced by an EntitlementProcess, its recurrenceType cannot be modified cleanly without removing it from the EntitlementProcess first.
How do you query MilestoneType definitions and active Case milestones in SOQL?
You can query the MilestoneType standard object for Name and RecurrenceType, and query CaseMilestone (or WorkOrderMilestone) to track IsCompleted, IsViolated, TargetDate, CompletionDate, and TimeRemainingInMins on live records.
Comments
Questions, corrections and tips are welcome. Comments are GitHub Discussions, so you sign in with GitHub.