SfSkills Domains Docs GitHub

Home / admin / chatter-notification-tuning

chatter-notification-tuning

Use when admins are reducing Chatter signal-to-noise across an org — covers org-level Chatter Email Settings, per-user Email Settings preferences, group-level email digest frequency (Daily / Weekly / Every post / Never), bell-icon Custom Notifications vs Chatter feed-post tradeoffs, automated-feed suppression on record types via Feed Tracking config, and the Chatter Settings org defaults that control whether new users start with everything-on.

Open the skill folder on GitHub


Chatter Notification Tuning

Activate this skill when an admin needs to reduce Chatter feed noise, lower email volume, or rebalance the notification surface across Chatter feed posts, Custom Notifications (bell), and email. The skill is about governance of the notification channel — not authoring new automation.

Group lifecycle — creation policy, archiving, ownership transfer, unlisted groups — belongs to admin/chatter-group-governance. That skill governs which groups exist; this one governs what is noisy inside them.


Before Starting

Gather this context before proposing changes:


Questions to Ask Before Configuring

Ask these before touching Setup, writing XML, or staging a CSV. Each one maps to a gotcha that turns a reasonable-looking tuning change into a change that fails, reverses itself, or overrides someone's deliberate choice.

AskWhy it mattersWhat a good answer adds
"Which channel is loud — the feed, the inbox, or the bell?"They are three different data stores with three different fixes; EntitySubscription (follows), CollaborationGroupMember (digests) and Messaging.CustomNotification (bell) share nothing but a complaintThe one surface to work on, instead of a plan that touches all three and cannot be measured
"Who is running the bulk change, and do they hold Modify All Data?"NotificationFrequency can only be set by the member or a Modify All Data holder (L67510–67513); a group owner's load fails per rowEither a named runner, or the decision to change only User.DefaultGroupNotificationFrequency and ask members to change their own
"Which of P / D / W / N is the intended default, and if it is P, why?"P self-disables above 10,000 members in a site and silently switches everyone to Daily (L67519–67522)A written justification the checker's CNT-POLICY-EVERYPOST will stop demanding, or a switch to D before that decision gets made for you
"Is the volume automated or human?"An 800-post Flow is not a digest problem — no frequency setting makes those posts worth readingThe routing decision between migrating a chatterPost action (examples § 3) and tuning frequency (examples § 2)
"Are we changing what new joins inherit, or rewriting existing members' choices?"User.DefaultGroupNotificationFrequency applies "when the user joins groups" (L295160–295163) and is not retroactive; rewriting CollaborationGroupMember rows overrides choices people madeTwo separate changes with two separate consent stories, rather than one that quietly does both
"Does this org have digital experiences enabled?"FeedItem.Visibility only exists if it does (L136412–136414), and for record posts it already defaults to InternalUsers (L136430–136431)Whether the external-exposure audit is real work or a wild goose chase
"What does 'quiet enough' look like, and against which number?"Without a before-measurement the change cannot be defended or reversed on evidenceThe 30-day FeedItem-by-Type baseline that step 7 re-runs against

What a proper configuration adds over just doing it: the org gets a notification policy that is written down, linted against the real group population and the real enum, deployed from source control, and measured against a before-baseline — instead of a one-off Setup change that nobody can explain in six months, built on a frequency value that does not exist, applied by someone whose permissions silently dropped half the rows.


Core Concepts

Concept 1 — Four control surfaces, and only two of them are metadata

SurfaceWhere it livesWhat it controlsSource
ChatterSettingssettings/Chatter.settings-meta.xmlenableChatter, enableApprovalRequest, feed presentationapi_meta.txt L112452–112648
ChatterEmailsMDSettingssettings/ChatterEmailsMD.settings-meta.xmlthe collaboration-email master switch, digest scheduling mode, email-to/reply-to-ChatterL112368–112445
User fieldsdata — Data Loader / DMLpersonal digest frequency, inherited group frequency, every per-event emailobject_reference.txt L295156–295207, L296132–296300
CollaborationGroupMember.NotificationFrequencydata — Data Loader / DMLone member's digest frequency in one groupL67503–67540

Two consequences follow from that table, and both are load-bearing.

There is no org-level default digest frequency. ChatterEmailsMDSettings has ten boolean elements and none of them is a frequency (L112383–112418). What new users inherit is the defaulted-on-create value of User.DefaultGroupNotificationFrequency: N, "but for Professional, Enterprise, Unlimited, and Developer Edition organizations that existed before API version 22.0, the default value remains D" (L295165–295172). In a long-lived Enterprise org, every new hire is inheriting a daily digest that nobody chose.

The only org-wide email lever is binary. enableCollaborationEmail — "whether collaboration email notifications can be sent (true) or not (false)" (L112391–112392). Setting it false makes every preference below it inert. It ends the complaint by ending the channel; treat it as a decision about whether the org uses Chatter email at all, not as a volume dial.

Concept 2 — Feed Tracking is what makes records noisy, and its failure modes are not the folklore ones

Feed Tracking is two elements that must travel together: enableFeeds on the object (api_meta.txt L42035–42039) and trackFeedHistory on each field, where "to set this field to true, the enableFeeds field on the associated CustomObject must also be true" (L43668–43672). Deploying the fields without the object is the most common failure, and the bundled checker raises CNT-TRACK-NO-FEEDS on it.

Two real failure modes, and one that gets blamed but cannot happen:

  1. Roll-up and formula fields. These recompute on dependent updates, so they generate feed activity

    with no human event behind it — the highest-yield removals when they are present. UNVERIFIED (2026-09-05): no supplied guide states whether roll-up summary or formula fields accept trackFeedHistory at all; the only documented eligibility restriction covers standard fields (L2164–2167). Read the retrieved *.field-meta.xml files for trackFeedHistory rather than assuming this category exists in the org in front of you.

  2. Whole-object tracking where a record type would do. recordTypeTrackFeedHistory

    (L42234–42241) scopes feed tracking to one record type, with the same enableFeeds prerequisite. When one integration-fed record type is the noise source, this is the surgical cut.

  3. Not LastModifiedDate. System fields "such as CreatedById or LastModifiedDate" are not

    eligible for feed tracking at all (L2164–2167). Anyone who reports finding it tracked is misremembering; sending an admin to look for that checkbox costs credibility.

Expect a smaller volume drop than the field-count drop suggests: a TrackedChange is "a change or group of changes to a tracked field" (object_reference.txt L136377–136378), so several fields changed in one save can collapse into one feed item.

Concept 3 — Custom Notifications (bell) vs Chatter feed posts

GoalUse
Targeted, transient alert ("your case was reassigned")Custom Notification (bell). No FeedItem written. Desktop and/or mobile channel.
Durable record of an event ("approval rejected on Opp #4567")Chatter FeedItem. Preserves the audit trail; ApprovalPost and TrackedChange types exist for exactly this.
Broadcast announcement ("system maintenance Sunday")Custom Notification with a GroupId or QueueId recipient, NOT a feed post on user records.
Process telemetry ("flow completed successfully")NEITHER. Email alert or a dashboard. Chatter is not a logging channel.

The migration is one actionType swap in the Flow — chatterPost (api_meta.txt L68655) to customNotificationAction, "available in API version 46.0 and later" (L68710) — plus a deployed CustomNotificationType. A Flow posting a feed item on every Closed Won produces thousands of FeedItem rows a year; the bell reaches the same people and writes none.

Two limits shape the recipient design. Messaging.CustomNotification.send() takes at most 500 values (apexrefguide.txt L166776–166778) — not 2,000 — but a single GroupId or QueueId counts as one value and expands to every active member (L166766–166776), which collapses most large fan-outs to a set of size one. And send() requires the Send Custom Notifications permission, failing without it (L166591–166594).

Concept 4 — Choosing among four frequencies, with N as the honest default

The design space is P / D / W / N (object_reference.txt L67515–67518). Match it to group purpose rather than reaching for one org-wide answer:

Group purposeFrequencyWhy
Broadcast / announcement (IsBroadcast = true)DLow post rate, high must-read; a daily digest is the whole point
Active project groupWA heartbeat that says "this is still moving" without an inbox per thread
Social / interest groupNPeople read these when they choose to; pushing them is what generates the complaint
Genuinely urgent, small, boundedPOnly with a written reason — and only if the group cannot grow past 10,000 members, above which P self-disables and everyone is switched to Daily (L67519–67522)

The org-wide question is a different one: what should a new member inherit? That is User.DefaultGroupNotificationFrequency, and N is both the platform's own current default (L295165–295168) and the defensible choice — it makes every noisier setting a decision somebody made rather than a default nobody noticed.


  1. Measure before you plan. Run the 30-day FeedItem-by-Type query in

    references/metadata-examples.md § 8 as a View All Data holder. The dominant Type routes the rest of this workflow, and the number is the baseline step 7 re-runs against. Record both in templates/chatter-notification-tuning-template.md § 1.

  2. Retrieve the metadata baseline and lint it.
    sf project retrieve start --metadata Settings:Chatter Settings:ChatterEmailsMD --target-org prod-audit
    python3 scripts/check_chatter_notification_tuning.py --manifest-dir force-app/main/default

    Two findings stop everything else. CNT-SETTINGS-ELEMENT means the file in source control contains an element the guide does not document, so nothing in it will deploy. CNT-EMAIL-MASTER means enableCollaborationEmail is already false — the channel is off, and whatever people are complaining about is not Chatter email. references/metadata-examples.md §§ 1–2 carry the deployable shapes.

  3. Prune Feed Tracking, if step 1 said TrackedChange. Remove roll-up and formula fields first;

    consider recordTypeTrackFeedHistory before removing tracking wholesale. Package the .object-meta.xml with the field files — CNT-TRACK-NO-FEEDS fires when you forget, and so does the deploy. references/examples.md § 4 works a twelve-field Account down to four.

  4. Migrate transient automated posts, if step 1 said TextPost from automation ids. The checker's

    CNT-FLOW-CHATTERPOST and CNT-APEX-FEEDITEM findings are the worklist. Swap chatterPost for customNotificationAction and deploy the CustomNotificationType (references/metadata-examples.md § 3). Keep durable business events on the feed — read references/llm-anti-patterns.md anti-pattern 7 before anyone proposes a FeedItem purge instead. Run the two in parallel for two weeks before deactivating the original.

  5. Write the digest policy down, then lint it against the real group population.
    sf data query --result-format csv --target-org prod \
        --query "SELECT Id, Name, IsBroadcast, IsArchived FROM CollaborationGroup" > groups.csv
    python3 scripts/check_chatter_notification_tuning.py \
        --manifest-dir force-app/main/default \
        --policy notification-policy.json --group-inventory groups.csv

    CNT-POLICY-GROUP catches overrides that name a group that no longer exists; CNT-FREQ-VALUE rejects L and Limited; CNT-POLICY-EVERYPOST makes you justify P in writing. The policy shape is in references/metadata-examples.md § 7.

  6. Apply it in two separate changes. First User.DefaultGroupNotificationFrequency and

    User.DigestFrequency, which only affect what people inherit going forward. Then, as a Modify All Data holder and only if you decided to, the CollaborationGroupMember rows — which override choices people made. Lint the CSV before each load:

    python3 scripts/check_chatter_notification_tuning.py --member-csv members_update.csv

    references/examples.md § 5 covers the per-user email flags and their inverted polarity; references/gotchas.md gotcha 9 is the one that turns a suppression load into an amplification.

  7. Re-measure at two weeks and diff. Re-run step 1's query and step 2's checker invocation. The

    dominant Type should have changed, not just shrunk — if TrackedChange still leads after a chatterPost migration, step 3 was the work that mattered and did not happen. Commit Chatter.settings, ChatterEmailsMD.settings, the notification types and the policy JSON so the next org inherits the decision rather than rediscovering it.


Reference Files

FileRead it when
references/metadata-examples.mdWriting the deployable ChatterEmailsMD.settings, Chatter.settings, CustomNotificationType or Feed Tracking XML, the package.xml and sf project commands — or any of the data-side artefacts: the policy JSON, the member and user CSVs, the DML alternative, and the verification queries
references/gotchas.mdThe change failed, reversed itself, or did the opposite of what you intended — an invalid NotificationFrequency, a settings element that will not deploy, a per-post setting that became Daily on its own, a send() that failed above 500, a suppression load that increased volume
references/examples.mdWorking a scenario end to end before any XML exists — the new-hire default, a bulk group-frequency change, a chatterPost migration, Feed Tracking pruning, per-user preference resets, and the audit query that routes between them
references/well-architected.mdJustifying bell vs feed, W vs D vs N, inherited-default vs rewrite, or source-suppression vs frequency-tuning — and locating the official source behind any claim in this skill
references/llm-anti-patterns.mdReviewing output an AI assistant produced here, especially anything mentioning Limited, an emailOn* settings element, a 2,000-recipient batch, the Tooling API, or a FeedItem purge
templates/chatter-notification-tuning-template.mdRunning workflow steps 1–4 — the diagnosis, the questions, the policy, and the record of what you deliberately left alone
scripts/check_chatter_notification_tuning.pyWorkflow steps 2, 5, 6 and 7 — before any settings deploy, before any policy is agreed, and before every CSV load

Package files