# Trail Assembly > Salesforce errors and what causes them. Vendor-neutral Salesforce documentation: 561 articles on Apex, Flow, LWC, administration, architecture and integration, each stating whether it was reproduced in an org or written from the documentation. Every article opens with a direct answer to the question in its title, then explains the causes, then closes with a frequently-asked section. Append `.md` to any article URL for a clean Markdown version (for example `https://trailassembly.com/cpu-time-limit.md`). ## Machine-readable indexes - [Full catalogue (JSON)](https://trailassembly.com/ai-index.json): every article with its answer, sections, FAQ, error codes and sources, as structured data. - [Full corpus (text)](https://trailassembly.com/llms-full.txt): every article's answer and FAQ in one file. - [Sitemap](https://trailassembly.com/sitemap_index.xml): canonical URLs and change dates. ## Admin and Permissions - [Transaction security](https://trailassembly.com/salesforce-transaction-security/): A transaction security policy watches a real-time event, evaluates a condition, and takes an action when the condition matches. Two ways to write the condition: Condition Builder for declarative… - [Text vs picklist](https://trailassembly.com/salesforce-text-vs-picklist/): Use a picklist whenever anyone will ever group, filter or report on the field, and use text only when the content is genuinely open. Free text is cheap to build and expensive forever after, because… - [Assets, and modelling what the customer owns](https://trailassembly.com/salesforce-assets/): The Asset object records what a specific customer actually owns — this product, this serial number, this account, with dates. Use it when support needs to know what is installed, when renewals… - [Just-in-time provisioning, and what it cannot set](https://trailassembly.com/jit-provisioning/): Just-in-time provisioning creates or updates a Salesforce user from SAML attributes at the moment they log in, so you never pre-create accounts. It sets the fields you send it and the permission sets… - [Why can this user see this record](https://trailassembly.com/why-can-this-user-see-this-record/): Work down the layers in order — org-wide default, role hierarchy, sharing rules, team membership, manual and Apex shares, implicit sharing, then profile-level View All. Stop at the first layer that… - [External Credentials and the new auth model](https://trailassembly.com/external-credentials/): A Named Credential now holds the URL and points at an External Credential, which holds the authentication. That split is the whole change. The authentication config is reusable across endpoints… - [Global value sets and picklist governance](https://trailassembly.com/global-value-sets/): A global value set is one list of picklist values shared by many fields, so "Country" means the same thing on five objects and you change it in one place. Use one wherever the same list appears… - [Sharing sets](https://trailassembly.com/salesforce-sharing-sets/): A sharing set grants Experience Cloud users on high-volume licences access to records by matching a lookup on the record against the Account or Contact on their own user record, and it exists because… - [Security tokens](https://trailassembly.com/salesforce-security-tokens/): A security token is a case-sensitive string Salesforce emails to a user, appended to their password when authenticating to the API from an untrusted network. It resets whenever the password changes… - [Search configuration](https://trailassembly.com/salesforce-search-configuration/): Search runs against an index, not against your data directly, and almost every "why can't I find this record" ticket comes down to one of four things: the object is not searchable, the field is not a… - [Scoping rules](https://trailassembly.com/salesforce-scoping-rules/): A scoping rule changes what a user sees by default without changing what they are allowed to see. It narrows the working set, not the permission. Restriction rules do the opposite: they remove access… - [Restriction rules](https://trailassembly.com/salesforce-restriction-rules/): Restriction rules are the only control in Salesforce that takes record access away. Everything else in the sharing model adds. A rule names a set of users and a record filter, and those users then… - [Related lists](https://trailassembly.com/salesforce-related-lists/): A related list is configured on the page layout, through the small wrench icon on the list itself, and that is where you set the columns, the sort and the buttons. The limits people run into are the… - [Profile retirement](https://trailassembly.com/salesforce-profile-retirement/): Salesforce announced in early 2023 that permissions on profiles would be retired, gave a target of Spring '26, and then cancelled it. Profiles are not going anywhere. That target release has now… - [Permission set expiration](https://trailassembly.com/salesforce-permission-set-expiration/): You can give a permission set or permission set group assignment an expiry date, after which the platform removes the access without anyone remembering to, which turns temporary access from a promise… - [Page layout strategy](https://trailassembly.com/salesforce-page-layout-strategy/): You need one page layout per genuinely different arrangement of the page, which is almost always far fewer than the number of layouts an org actually has. Layouts multiply because assignment is a… - [Number currency percent](https://trailassembly.com/salesforce-number-currency-percent/): Number, currency and percent fields all store a decimal with a fixed precision and scale you choose at creation, and almost every "the total is wrong by a penny" report traces back to rounding… - [Lookup filters](https://trailassembly.com/salesforce-lookup-filters/): A lookup filter restricts which records a user can pick in a lookup field, and the only decision that really matters is required versus optional. A required filter is a rule enforced on save, so it… - [List view charts](https://trailassembly.com/salesforce-list-view-charts/): A list view chart is a single grouping of the records already in the list, drawn as a donut or a bar chart, and it exists to tell the person working that list where their attention should go. It… - [Home page design](https://trailassembly.com/salesforce-home-page-design/): A home page earns its place only if it answers "what should I do next" without scrolling. Build it in the Lightning App Builder, keep it to three or four components, and assign it per app and profile… - [Formula functions](https://trailassembly.com/salesforce-formula-functions/): About a dozen formula functions cover nearly everything you will ever write, and the ones that get you into trouble are not the complicated ones. CASE, BLANKVALUE, TEXT and DATEVALUE handle the… - [Event monitoring](https://trailassembly.com/salesforce-event-monitoring/): Event Monitoring gives you machine-readable logs of what users and integrations actually did, delivered as daily or hourly CSV files on the EventLogFile object, plus a set of real-time events that… - [Dependent picklists](https://trailassembly.com/salesforce-dependent-picklists/): A dependent picklist limits its own values based on what is selected in a controlling field, and the whole feature lives in one matrix screen on the dependent field. It is enforced properly in the… - [Audit preparation](https://trailassembly.com/salesforce-audit-preparation/): An auditor wants evidence that access is granted deliberately, reviewed periodically, removed promptly and logged throughout. Almost all of it can be extracted from Salesforce with a handful of… - [Penetration testing a Salesforce org](https://trailassembly.com/penetration-testing-salesforce/): Salesforce permits customers to penetration test their own orgs, but only after you have accepted its penetration testing agreement, and the terms rule out anything that stresses shared… - [Manual shares and Apex managed sharing](https://trailassembly.com/manual-sharing-and-apex-sharing/): Every sharable object has a shadow object holding one row per grant, and both manual shares and Apex managed sharing write rows to it. The difference is the RowCause. A manual share is deleted the… - [Implicit sharing on accounts](https://trailassembly.com/implicit-sharing/): Implicit sharing is access the platform grants automatically between accounts and their child records, in both directions, without any rule you configured. Read on a child case gives read on the… - [Field Audit Trail and long-term history](https://trailassembly.com/field-audit-trail/): Field Audit Trail extends field history retention well past the standard window, raises how many fields you can track per object, and moves aged history into a big object called FieldHistoryArchive… - [Deactivating a user properly](https://trailassembly.com/salesforce-user-deactivation/): Unticking Active ends the person's sessions and releases their licence, and does almost nothing else. They still own every record they owned. Their open tasks stay theirs. Pending approvals sit with… - [Reading the Setup Audit Trail properly](https://trailassembly.com/salesforce-setup-audit-trail/): The Setup Audit Trail records who changed what in Setup for the last six months, it does not record data changes or before-and-after values, and if you have not been exporting it then anything older… - [The per-object limits page](https://trailassembly.com/salesforce-object-limits-page/): Object Manager, pick an object, then Object Limits. It lists the per-object ceilings with a used count, a maximum and a percentage. Most of them you will never approach. Three of them decide the… - [Login As: what is audited and what is not](https://trailassembly.com/salesforce-login-as-user/): Login As lets an administrator take over another user's session and see exactly what they see. It needs a Login Access Policies setting plus a user management permission, and the detail that matters… - [Inline editing and mass actions](https://trailassembly.com/salesforce-inline-editing-and-mass-actions/): Inline editing works on record pages and list views, mass inline edit handles up to 200 records at a time, and mass quick actions handle up to 100. All three run the full save path, so validation… - [Delegated administration, and its risks](https://trailassembly.com/salesforce-delegated-administration/): Delegated administration lets a named group manage users within specific roles, assign a fixed list of profiles and permission sets, and administer named custom objects, without granting anything… - [Data classification metadata on fields](https://trailassembly.com/salesforce-data-classification/): Every field in Salesforce carries four pieces of classification metadata: compliance categorisation, data sensitivity level, data owner and field usage. None of it enforces anything. It is… - [Automating tasks without drowning users](https://trailassembly.com/salesforce-tasks-automation/): Creating a task from automation is trivially easy, which is the whole problem. A record-triggered flow with a Create Records element pointed at Task takes two minutes, and six of those built by six… - [Org-wide email addresses and bounce behaviour](https://trailassembly.com/salesforce-org-wide-email-addresses/): An org-wide email address lets mail leave Salesforce with a From address like support@yourcompany.com instead of the sending user's own address. It has to be verified by someone who can read that… - [Email template types, and where each works](https://trailassembly.com/salesforce-email-templates/): There are Classic templates (Text, HTML with letterhead, Custom HTML, Visualforce), and Lightning templates, and the two families use different merge syntax and are usable in different places. The… - [Custom notifications from flow and Apex](https://trailassembly.com/salesforce-custom-notifications/): A custom notification is a bell alert in Lightning and a push message on the Salesforce mobile app, sent from a flow or from Apex. Define a notification type once, choose its channels, then send it… - [Configuring Chatter, and what to turn off](https://trailassembly.com/salesforce-chatter-configuration/): Chatter configuration is four decisions, not one. Which fields generate feed entries, which group types exist, which invitation and email settings stay on, and who can moderate. Get feed tracking… - [Session security settings](https://trailassembly.com/session-security-settings/): Set a session timeout you can defend, turn on force logout, and leave "lock sessions to the IP address from which they originated" switched off unless your network egress is genuinely fixed. That one… - [The utility bar, and what belongs there](https://trailassembly.com/salesforce-utility-bar/): The utility bar is configured per Lightning app in App Manager, and it is the only place in the interface that survives navigation. A component there keeps its state while the user moves between… - [Salesforce Surveys, linked to a case](https://trailassembly.com/salesforce-surveys/): Salesforce Surveys stores a survey as a versioned record, sends it through an invitation that carries a unique link, and writes answers back as one record per question. That last detail is the one… - [Products and catalogues at scale](https://trailassembly.com/salesforce-products-and-catalogs/): Product2 is a flat list. It has a single Family picklist, no hierarchy, no variants and no versioning, and every price lives on a separate PricebookEntry. A catalogue of any size outgrows that shape… - [Path and guidance for success](https://trailassembly.com/salesforce-path-and-guidance/): Path turns a picklist into a set of steps across the top of a record page, and each step can carry up to five key fields plus a block of guidance text. It is configured in Path Settings, one path per… - [The Salesforce mobile app, configured](https://trailassembly.com/salesforce-mobile-app-setup/): An admin controls four things on mobile, and they are not the four people expect. The compact layout decides what appears in the record header. The page layout's mobile and Lightning actions section… - [Certificates and key management](https://trailassembly.com/salesforce-certificates-and-keys/): Use a self-signed certificate when only Salesforce and a system you control need to trust it, and a CA-signed one when a third party does. Create it non-exportable unless you have a concrete reason… - [Buttons, quick actions and list view actions](https://trailassembly.com/list-view-buttons-and-actions/): Quick actions appear on record pages and in the mobile action bar, custom detail page buttons appear on record pages only if you add them to the layout, and list view buttons appear on list views and… - [Lightning App Builder: record, app and home pages](https://trailassembly.com/lightning-app-builder-pages/): The App Builder makes three kinds of page, and only record pages have interesting assignment rules. A record page can be the org default, an app default, or assigned to a specific combination of app… - [Field Service: work orders and scheduling](https://trailassembly.com/field-service-basics/): A work order says what needs doing, a service appointment says when and by whom, and a service resource is the person or asset who does it. The platform gives you those objects. The scheduling… - [Login and self-registration for a community](https://trailassembly.com/experience-cloud-login-and-registration/): Login, registration and password behaviour for a site are configured in the site's Administration area under Login & Registration, and password policy comes from the external user's profile, not from… - [Dynamic Forms and Dynamic Actions](https://trailassembly.com/dynamic-forms-and-actions/): Dynamic Forms moves fields out of the page layout and onto the Lightning record page, where each field and section can carry visibility rules. Dynamic Actions does the same for buttons. Neither… - [Compact layouts and the highlights panel](https://trailassembly.com/compact-layouts/): A compact layout holds up to ten fields, is assigned per record type, and drives the highlights panel on desktop, the record header in the mobile app, and the preview cards that appear in several… - [Designing a case status model](https://trailassembly.com/case-status-design/): Status is one picklist, and IsClosed is a property of each picklist value rather than a field anybody sets. You can have several closed statuses. You cannot have a status that is half closed, and… - [Web-to-Case: the daily limit and what happens past it](https://trailassembly.com/web-to-case-limits/): Web-to-Case accepts up to 5,000 cases per day per org. Requests beyond that go into a pending queue and are processed when the daily allowance resets, and once that queue is full the rest are… - [SSO with SAML: the five settings that cause every failure](https://trailassembly.com/sso-with-saml/): SAML failures are almost never mysterious. Five values have to line up between the identity provider and Salesforce, and when a login breaks it is one of them: entity ID, ACS URL, name ID, signing… - [The Service Console, configured properly](https://trailassembly.com/service-console-productivity/): The console exists to stop agents losing their place. Workspace tabs hold the thing they are working on, subtabs hold everything they open from it, and the utility bar holds the tools that must… - [Enterprise Territory Management](https://trailassembly.com/salesforce-territory-management/): Enterprise Territory Management is a second sharing mechanism that assigns accounts to territories by rule, assigns users to territories, and grants access from that pairing. Its real advantage over… - [Quotes, and the sync direction problem](https://trailassembly.com/salesforce-quotes/): A Quote is a snapshot of an opportunity's products with its own totals, dates and PDF. One quote at a time can be synced back to the opportunity, and while that sync is on, edits flow in both… - [MFA: what is required and what satisfies it](https://trailassembly.com/salesforce-mfa-requirements/): Every human who logs in to Salesforce directly needs a second factor, and Salesforce now enforces that rather than asking. What counts is an authenticator app, a security key, or a built-in device… - [Macros and quick text for support agents](https://trailassembly.com/salesforce-macros-and-quick-text/): Quick text inserts a block of wording into whatever the agent is typing, and a macro clicks a sequence of buttons on the record they already have open. Neither is automation in the flow sense. A… - [Salesforce Knowledge: articles, versions and publishing](https://trailassembly.com/salesforce-knowledge-setup/): Lightning Knowledge is one object, Knowledge__kav, where record types replace the old article types and every edit creates a new version. An article has a stable article record underneath it and a… - [The Contract object, and when to build your own](https://trailassembly.com/salesforce-contracts/): The standard Contract object is a record of an agreement with an account, a date range, a status lifecycle and a signature trail. It has no line items, no versioning, no amendments and no renewal… - [Chat: deployments, buttons and routing](https://trailassembly.com/salesforce-chat-setup/): Chat, the feature formerly called Live Agent, is a synchronous web chat built from a deployment, one or more buttons, and an agent configuration. It works, it is well understood, and Salesforce has… - [Campaigns, members and influence, honestly](https://trailassembly.com/salesforce-campaigns-and-influence/): A Campaign is a container, a CampaignMember is a person's relationship to it, and campaign influence is an attempt to credit revenue back to campaigns. The first two are solid. The third is a… - [Reading Login History like an inventory](https://trailassembly.com/reading-login-history/): Login History is the only complete list of things that authenticate to your org, and almost nobody reads it as one. Four columns do the work: Application, API Type, API Version and Source IP. Sort by… - [Opportunity teams and splits](https://trailassembly.com/opportunity-team-and-splits/): An opportunity team grants people access to a deal and gives them a role. An opportunity split assigns them credit, in percentage terms, against a currency field. Teams are a sharing feature. Splits… - [Opportunity stages, probability and forecast category](https://trailassembly.com/opportunity-stages-and-probability/): A stage is a picklist value on Opportunity that carries three passengers with it: a default probability, a forecast category, and an open or closed flag. Most orgs have too many stages, treat… - [Opportunity products and revenue schedules](https://trailassembly.com/opportunity-products-and-schedules/): An opportunity product (OpportunityLineItem) is a priced product on a deal, and a schedule breaks that line into dated instalments of revenue, quantity, or both. Schedules solve a real problem and… - [My Domain and enhanced domains](https://trailassembly.com/my-domain-and-enhanced-domains/): My Domain gives your org its own hostname, and enhanced domains removed the instance name from every Salesforce URL your users and integrations touch. The work is done for most orgs now. What remains… - [Messaging for In-App and Web](https://trailassembly.com/messaging-for-in-app-and-web/): Messaging for In-App and Web is asynchronous. The customer can close the tab, get on a train, come back an hour later and the conversation is still there. That single difference from Chat changes the… - [Lead assignment rules and lead scoring](https://trailassembly.com/lead-assignment-and-scoring/): One assignment rule is active at a time, its entries are evaluated in order, and the first match wins. If nothing matches, the lead goes to the Default Lead Owner and nobody hears about it. That… - [Data categories, and why an article is invisible](https://trailassembly.com/knowledge-data-categories/): Data categories classify articles, and category visibility decides who can see what. An article is invisible to a user for one of four reasons: it is not published, its channel excludes them, its… - [Experience Cloud sharing: sharing sets and share groups](https://trailassembly.com/experience-cloud-sharing/): External users read a different org-wide default from internal users, and the mechanism that grants them records depends on their licence. High-volume users (Customer Community) get access through… - [SEO for an Experience Cloud site](https://trailassembly.com/experience-cloud-seo/): Only pages the guest user can see are indexable, and only pages you have explicitly marked as public and indexable end up in the generated sitemap. An LWR site renders on the server, so a crawler… - [Experience Cloud licence types compared](https://trailassembly.com/experience-cloud-licence-types/): Customer Community is a high-volume licence with no role, no sharing rules and no access to Opportunities or Leads. Customer Community Plus adds a role, sharing rules, reports and delegated… - [Einstein Activity Capture, and where your activities go](https://trailassembly.com/einstein-activity-capture/): Einstein Activity Capture connects a user's mailbox and calendar to Salesforce and shows the emails and meetings on the activity timeline. Most of that data is not stored in Salesforce objects. It… - [Merging cases, and what merge destroys](https://trailassembly.com/case-merge-and-related-cases/): Merging cases consolidates duplicates into one master and is not reversible. Parent and child cases are a different tool entirely, for one real problem that produced several reports, and nothing is… - [Case Feed and the publisher actions](https://trailassembly.com/case-feed-and-publisher/): Case Feed turns the case record into a chronological record of what happened, with the publisher at the top for doing the next thing. What an agent can do from that publisher comes from the actions… - [Case escalation rules, and why they seem not to fire](https://trailassembly.com/case-escalation-rules/): An escalation rule watches a case's age against a set of criteria and fires actions when the age passes a threshold. Only one escalation rule per object can be active. When it appears not to fire… - [Tasks and Events: one object, two behaviours](https://trailassembly.com/activities-tasks-and-events/): Task and Event are two separate objects that share one set of custom fields, one pair of polymorphic lookups, and one confusing name. You cannot query Activity. You can report on both together in… - [Validation rule patterns that work](https://trailassembly.com/salesforce-validation-rule-patterns/): A validation rule fires when the formula returns TRUE, which means you write the condition for the bad state, not the good one. That inversion is behind most broken rules. The other half of getting… - [Reading your own data model](https://trailassembly.com/salesforce-schema-builder-and-erd/): Schema Builder is a live view of your org's objects and relationships, and it is genuinely useful for about a dozen objects at a time. It is not a documentation tool. It cannot export, it cannot lay… - [Queues, public groups, roles and territories](https://trailassembly.com/salesforce-queues-and-groups/): A queue owns records, a public group does not. That single difference decides which one you need. Roles drive hierarchical record access and roll-up reporting, and territories drive account and… - [Managing picklists at scale](https://trailassembly.com/salesforce-picklist-management/): The label a user sees and the value stored in the database are two different things, and every picklist problem that survives more than a day comes from that gap. Manage shared lists as global value… - [List views: sharing, filter logic and scope](https://trailassembly.com/salesforce-list-views-and-filters/): A list view has three independent controls, and confusing them is why list views misbehave. Visibility decides who can select the view. Scope decides which records are considered before any filter… - [Custom permissions, and the bypass pattern](https://trailassembly.com/salesforce-custom-permissions/): A custom permission is a named flag you assign through a permission set and then check in a formula, a flow, or Apex. It grants nothing on its own. Its value is that it turns "is this user allowed to… - [Multi-currency: the switch you cannot undo](https://trailassembly.com/salesforce-currency-management/): Enabling multi-currency is permanent. Salesforce does not turn it off again, and every currency field in the org gains a currency code and a conversion behaviour from that moment. Turn it on when you… - [Roll-up summary fields: what they can and cannot do](https://trailassembly.com/roll-up-summary-fields/): A roll-up summary field counts or aggregates child records, and it only works across a master-detail relationship. Four operations, one direction, up to 25 per object by default. If your relationship… - [Record types and page layout assignment](https://trailassembly.com/record-types-and-page-layouts/): A record type controls which picklist values are available, which business process applies, and which page layout a user sees. Layout assignment is a grid of profile against record type, so the… - [Field history tracking, and what it misses](https://trailassembly.com/field-history-tracking/): Field history tracking records old and new values for up to 20 fields per object, and Salesforce retains that history for a limited window rather than forever. It answers "who changed this field on… - [Cross-object formulas and their constraints](https://trailassembly.com/cross-object-formulas/): A cross-object formula walks upwards only. It follows lookup and master-detail relationships from child to parent, up to ten relationships away, and it cannot go the other direction because the other… - [Lead conversion: what it writes, and what it silently drops](https://trailassembly.com/lead-conversion-field-mapping/): Standard lead fields map by convention, custom lead fields map only if you map them by hand, and anything unmapped stops at the Lead and is never looked at again. Do the mapping before you convert… - [Email deliverability settings that stop your mail vanishing](https://trailassembly.com/email-deliverability-settings/): Setup, Email, Deliverability, and the field called Access to Send Email. If mail is disappearing with no error anywhere, check that first. In a sandbox it is nearly always the answer, because… - [Trusted IP ranges vs profile login IP ranges](https://trailassembly.com/trusted-ip-vs-login-ip-ranges/): Trusted IP Ranges only decide whether a user is asked for an identity verification code. Profile Login IP Ranges decide whether the user gets in at all. The profile restriction is checked first and a… - [The guest user security model](https://trailassembly.com/guest-user-security-model/): A guest user is an unauthenticated visitor holding a profile and almost no ability to touch data. Since the guest user security policies became mandatory, guest users cannot own records, the org-wide… - [View All, Modify All, View All Data, Modify All Data](https://trailassembly.com/view-all-modify-all-explained/): View All and Modify All are object permissions that ignore sharing for one object. View All Data and Modify All Data are system permissions that ignore sharing for every object in the org. Use the… - [Shield Platform Encryption: what breaks](https://trailassembly.com/shield-platform-encryption-what-breaks/): Shield Platform Encryption protects data at rest, and you pay for it everywhere the platform wants to compare, sort or calculate. Probabilistic encryption removes a field from WHERE clauses, ORDER… - [Duplicate rules and matching rules, in practice](https://trailassembly.com/salesforce-duplicate-rules/): A matching rule defines what counts as a duplicate, and a duplicate rule decides what to do about it. You need both, the matching rule must be activated separately, and the whole feature is bypassed… - [Migrating from profiles to permission sets](https://trailassembly.com/profiles-to-permission-sets-migration/): Build the permission sets first, assign them alongside the existing profile, prove nothing broke, and only then empty the profile out. Users move to a minimal profile last, one group at a time. Five… - [Price books, entries, and the pricebook entry that does not exist](https://trailassembly.com/price-books-and-entries/): A Product exists once, a PricebookEntry gives it a price in one price book, and an OpportunityLineItem points at a PricebookEntry rather than at the Product. Three levels, and almost every "pricebook… - [Omni-Channel routing: capacity, priority, and the agent getting nothing](https://trailassembly.com/omni-channel-routing/): Omni-Channel pushes work to agents based on capacity and priority rather than letting them pick from a queue. An agent gets nothing when their capacity is full, their status does not accept that work… - [Object permissions vs record access](https://trailassembly.com/object-permissions-vs-record-access/): Object permissions decide whether you may touch that kind of record at all. Sharing decides which rows you get. They are evaluated independently, and neither one ever compensates for the other. A… - [Entitlements and milestones, explained by what the timer does](https://trailassembly.com/entitlements-and-milestones/): An entitlement says a customer is owed support, and a milestone is a clock against a step of that support. The clock is the hard part: it starts when the milestone becomes applicable, stops when the… - [Email-to-Case: threading, duplicates, and the on-demand version](https://trailassembly.com/email-to-case-threading/): Email-to-Case matches a reply to an existing case using a thread token, and when that token is missing or mangled the reply becomes a new case. Salesforce moved from a visible token in the subject… - [ContentDocumentLink sharing, and the access nobody expects](https://trailassembly.com/contentdocumentlink-sharing/): A file's access comes from its links, and a link with ShareType = 'I' inherits permission from whatever record it points at. So a file becomes visible to everyone who can see any record it is linked… - [Case assignment rules: order, criteria, and the silent no-match](https://trailassembly.com/case-assignment-rules/): Assignment rules evaluate entry by entry, top to bottom, and stop at the first match. Only one rule per object can be active at a time, so "rules" plural means entries within one rule. The silent… - [INSUFFICIENT_ACCESS_OR_READONLY: six causes, one message](https://trailassembly.com/insufficient-access-or-readonly/): Salesforce deliberately does not say which. UserRecordAccess answers the access question directly, and an approval-process lock produces an identical error that sends people hunting through sharing… - [Permission set groups, and muting — the only subtractive tool you get](https://trailassembly.com/permission-set-groups-and-muting/): Permission set groups exist so you can assign a job role in one action instead of eleven, and muting exists because sooner or later a group grants one permission you cannot live with. Muting is the… - [What profiles still uniquely control](https://trailassembly.com/what-profiles-still-control/): Nine things, and page layout assignment is the one that keeps profiles in your org forever. Every user still has exactly one profile, and a permission set cannot assign a page layout, set a default… - [Permission sets after the cancelled profile retirement: what to do now](https://trailassembly.com/permission-sets-after-cancellation/): Profiles are not being retired. Salesforce cancelled the end-of-life for permissions on profiles that had been planned for Spring '26, and said so in a Help article published on 6 June 2026: "This… - [Sharing rules: criteria-based vs owner-based](https://trailassembly.com/sharing-rules/): Criteria-based rules cannot use formula, lookup, encrypted, or derived fields, which ends most designs before they start. Why volatile criteria fields are expensive, and what manual sharing and Apex… - [Role hierarchy design that survives a reorg](https://trailassembly.com/role-hierarchy/): Roles control record visibility, not permissions, and moving someone up the tree to fix a permission problem is the most expensive wrong answer available. Why depth costs more than breadth in the… - [Org-wide defaults explained by outcome, not theory](https://trailassembly.com/org-wide-defaults/): OWD answers one question: what can a user do with a record they do not own? Every other sharing feature only adds on top. Why Public Read/Write means the object has no sharing table at all, what… - [Formula field limits and the compile size error](https://trailassembly.com/formula-compile-size/): The character count you can see in the editor and the compiled size that actually errors are two different numbers, and only one of them is visible to you. Formulas are capped at 3,900 characters and… - [Dynamic Forms vs page layouts](https://trailassembly.com/dynamic-forms/): After migrating, the page layout still drives related lists, actions on standard objects, and the printable view. The supported-object test, the migration and rollback path, why visibility rules are… - [Record types: when they help and when they metastasise](https://trailassembly.com/record-types/): Worth it for picklist value subsets, layouts, and business processes, and they cost you a record-types-by-profiles layout grid forever. What to use instead, and why deactivating one freezes it rather… - [Validation rule, before-save flow, or required field?](https://trailassembly.com/validation-rule-vs-flow/): Before-save flows run at step 3 of the save order and validation rules at step 5, which settles most of this argument. Compares field-level required, layout required, validation rules, Custom Error… - [Who changed this field? Setup Audit Trail, field history, and what neither tells you](https://trailassembly.com/who-changed-this-field/): Three different tools answer three different questions. Setup Audit Trail tells you who changed the configuration. Field history tells you who changed the data, but only on fields you turned tracking… - [User access policies, and the risk of automating access](https://trailassembly.com/user-access-policies/): User access policies let you define criteria on the User record and have Salesforce grant or revoke permission sets, permission set groups, group memberships, queue memberships and package licences… ## Apex and Development - [SINGLE_EMAIL_LIMIT_EXCEEDED](https://trailassembly.com/single-email-limit-exceeded/): The daily single email limit counts every recipient, including ones queued earlier in the same transaction, and you can test it without sending mail. - [Queueable delays, and the duplicate check that costs a slot](https://trailassembly.com/queueable-delay-asyncoptions/): System.enqueueJob accepts a delay of up to 10 minutes, and a duplicate that AsyncOptions rejects still uses one of your 50 enqueues. - [System.MathException: Divide by 0](https://trailassembly.com/divide-by-zero-apex/): Apex throws Divide by 0 for every number type, Double included, while formula fields, flows and validation rules each fail in a different way. - [What an aggregate SOQL query costs against the row limit](https://trailassembly.com/aggregate-soql-query-limits/): An AggregateResult query does not charge you one query row per record, and it does not reliably charge you one per group either. COUNT(Id) charges one row per group returned. The moment you add SUM… - [USER_MODE: enforcing permissions in Apex](https://trailassembly.com/apex-user-mode/): Apex runs in system mode by default, which ignores the running user's object, field and record permissions. WITH USER_MODE on a SOQL query and AccessLevel.USER_MODE on a DML call make the platform… - [Apex Finalizers for Queueable error handling](https://trailassembly.com/apex-finalizers/): A Finalizer is a class attached to a Queueable job that runs after the job finishes, whether it succeeded or died on an uncatchable exception. It is the only way to log or recover from a… - [Apex Cursors, and when they beat Batch Apex](https://trailassembly.com/apex-cursors/): Apex Cursors let you page through a large query result inside ordinary synchronous or queueable Apex, fetching up to 2,000 rows at a time from a stable server-side result set, without the ceremony of… - [Non-selective query against large object type](https://trailassembly.com/non-selective-query-large-object/): Your query filters on a field that has no usable index, against an object big enough that Salesforce refuses to table-scan it. Add a filter on an indexed field that cuts the result below the… - [PK chunking for large extracts](https://trailassembly.com/salesforce-pk-chunking/): PK chunking splits a Bulk API 1.0 query into a series of batches bounded by record ID ranges rather than by row counts, so Salesforce never has to hold a single enormous result set in memory. You… - [Bulk API query or ordinary SOQL](https://trailassembly.com/bulk-query-vs-soql/): Ordinary SOQL through the REST or SOAP API can return any number of rows if you are willing to page through them, but you pay an API call per page of at most 2,000 records. Bulk API 2.0 query is… - [Enforcing CRUD and FLS for LWC](https://trailassembly.com/apex-crud-fls-in-lwc/): A Lightning web component enforces nothing. If it reads data through an Apex controller, that controller is the only thing standing between a user and data they should not see, and Apex does not… - [SOQL relationship queries and their limits](https://trailassembly.com/soql-relationship-queries/): SOQL walks relationships in two directions with different rules. Going up to parents you can traverse several levels using dot notation, and going down to children you get subqueries but only one… - [SOQL date literals and date functions](https://trailassembly.com/soql-date-literals-and-functions/): Date literals such as LAST_N_DAYS:30 are relative ranges you put in a WHERE clause, and date functions such as CALENDAR_MONTH() extract a component of a date so you can group by it. The catch that… - [Visualforce remoting, and what replaced it](https://trailassembly.com/apex-visualforce-remoting/): JavaScript remoting is a way to call a static Apex method from a Visualforce page without a postback and without view state, and Remote Objects is a declarative way to do basic record CRUD from… - [Controlling order inside one trigger handler](https://trailassembly.com/apex-triggers-and-order/): The platform guarantees the order of the stages (before triggers, system validation, after triggers, assignment rules, workflow, flows, roll up summaries) but it guarantees nothing about the order in… - [Apex String methods worth knowing](https://trailassembly.com/apex-string-methods/): Most Apex string bugs come from three places. Using isEmpty when you meant isBlank, calling split without a limit and silently losing trailing empty values, and concatenating user input into dynamic… - [Describe calls, and getting a record type Id safely](https://trailassembly.com/apex-sobject-describe/): Stop calling Schema.getGlobalDescribe(). It builds a map of every object in the org, which on a mature org with managed packages is thousands of entries, and it costs real CPU and heap every time you… - [Testing Schedulable and Batchable classes](https://trailassembly.com/apex-schedulable-testing/): Wrap the scheduling or the batch launch in Test.startTest() and Test.stopTest(), and the asynchronous work runs synchronously before stopTest returns. For a batch, only one call to execute is… - [Savepoints and rollback in Apex](https://trailassembly.com/apex-savepoints-and-rollback/): A savepoint marks a point in the current transaction that you can return to with Database.rollback. Recent API versions cap you at five savepoints and five rollbacks per transaction, and each of… - [Null-safe patterns in Apex](https://trailassembly.com/apex-null-safe-patterns/): The safe navigation operator ?. stops a null pointer exception on the way to a value, and the null coalescing operator ?? supplies a replacement once you have one. Between them they remove most… - [Calling the Metadata API from Apex](https://trailassembly.com/apex-metadata-api-from-apex/): The Metadata namespace lets Apex read and deploy a small set of metadata types, with custom metadata type records and page layouts being the ones people actually use. Deployments are asynchronous and… - [Interfaces and abstract classes in Apex](https://trailassembly.com/apex-interfaces-and-abstract/): Use an interface when you need a contract that several unrelated classes can satisfy, and an abstract class when the implementations share real code or state. Apex has no multiple inheritance, so a… - [Governor limits inside tests](https://trailassembly.com/apex-governor-limits-in-tests/): Test.startTest() gives the code between it and Test.stopTest() a fresh set of governor limits, so the records you created during setup do not spend the budget you want to measure. It does not start a… - [A durable exception logging pattern](https://trailassembly.com/apex-exception-logging-pattern/): Log to a custom object, but publish the log through a platform event configured to publish immediately, because an insert made inside a transaction that then fails is rolled back along with… - [Inbound email services in Apex](https://trailassembly.com/apex-email-services/): An email service is an Apex class implementing Messaging.InboundEmailHandler, bound to one or more generated email addresses, that receives a parsed message and returns a result object. Setting… - [Building dynamic SOQL safely](https://trailassembly.com/apex-dynamic-soql-safely/): Bind every value, allow list every identifier. Values go into the query through bind variables so they are never parsed as SOQL, and object or field names, which cannot be bound, get checked against… - [Database.insert or plain DML](https://trailassembly.com/apex-database-methods/): Plain insert records; is all or nothing and throws a DmlException on the first failure. Database.insert(records, false) commits the rows that worked, returns a result per record, and throws nothing… - [Sorting in Apex, and implementing Comparable](https://trailassembly.com/apex-comparable-and-sorting/): If the data came from a query, sort it with ORDER BY and stop reading. If it did not, List.sort() handles primitives correctly on its own, Comparable gives a class one natural order, and Comparator… - [List, Set and Map: choosing correctly](https://trailassembly.com/apex-collections-choosing/): Use a List when order matters or duplicates are legitimate, a Set when membership is the only question you ask, and a Map when you look things up by a key. The decision that actually costs you money… - [Platform Cache: when it earns its cost](https://trailassembly.com/platform-cache-when-worth-it/): Platform Cache stores data in memory across transactions, in two flavours. Org cache is shared by everyone, session cache is per user session. It earns its cost when you have expensive… - [The Apex flex queue](https://trailassembly.com/apex-flex-queue/): The flex queue holds batch jobs waiting to run. Five Apex jobs can be active or queued at once, and up to 100 more sit in Holding status until a slot opens. You can reorder Holding jobs, you cannot… - [Why every database test should insert 200 records](https://trailassembly.com/testing-at-200-records/): A test that inserts one record proves your code compiles and runs. It proves nothing about whether it works. Insert 200, because that is the trigger chunk size, and a whole category of defect only… - [Queueable chaining and its limits](https://trailassembly.com/queueable-chaining-limits/): A queueable job can enqueue exactly one child job. That single rule is what makes chaining work and what stops it becoming a fork bomb. There is no published depth limit in production, but the chain… - [How managed packages consume your limits](https://trailassembly.com/managed-package-limits/): Code in a certified managed package gets its own allowance for most per-transaction limits, so a packaged trigger firing alongside yours does not spend your 100 queries. The limits that are not… - [Instrumenting with the Limits class](https://trailassembly.com/instrumenting-with-limits-class/): The Limits class gives you a live counter and a ceiling for every governor limit, and the only reliable way to find what a transaction actually costs is to read those counters around the code you… - [Heap: SOQL for-loop against list assignment](https://trailassembly.com/heap-soql-for-loop/): A SOQL for-loop pulls records in batches of 200 and lets each batch go out of scope, so heap stays roughly constant no matter how many rows you process. List assignment holds every row at once. Use… - [The 10 concurrent long-running request limit](https://trailassembly.com/concurrent-long-running-requests/): An org can have 10 synchronous Apex requests running longer than 5 seconds at the same time. The eleventh is rejected. The limit is org-wide, not per user, so one slow page opened by twenty people… - [Caching describe calls to cut CPU](https://trailassembly.com/caching-describes/): Schema.getGlobalDescribe() builds a map of every object in the org, and calling it twice costs twice. Cache the results you need in a lazily populated static, and prefer the targeted describe calls… - [Bulkification patterns that scale](https://trailassembly.com/bulkification-patterns/): Bulkification is three shapes. Query once into a Map, build a collection and do one DML at the end, and decide deliberately whether a failure should take the whole batch down. Everything else is… - [Batch scope sizing, and why 200 is not always right](https://trailassembly.com/batch-apex-scope-sizing/): 200 is the default, not the right answer. Scope should be set by the heaviest record your batch will see, not the average one, because a single execute that exceeds CPU or heap kills that chunk and… - [Callout limits, and the patterns around them](https://trailassembly.com/apex-callout-limits-patterns/): 100 callouts per transaction and 120 seconds of cumulative callout time. The second one is the ceiling that actually stops people, because a slow endpoint burns it with a handful of requests. Design… - [UNABLE_TO_LOCK_ROW in test classes](https://trailassembly.com/unable-to-lock-row-in-tests/): Your test methods are running at the same time and two of them are writing the same record. Apex tests run in parallel by default, and parallelism plus shared data equals row lock contention. The… - [Too many queueable jobs added to the queue: 51](https://trailassembly.com/too-many-queueable-jobs/): A synchronous transaction may enqueue 50 Queueable jobs, and you asked for a 51st. The message counts for you: Too many queueable jobs added to the queue: 51. If the enqueue happened from inside… - [STORAGE_LIMIT_EXCEEDED](https://trailassembly.com/storage-limit-exceeded/): The org is out of data storage, and data storage is counted separately from file storage. Being at 30% on files does not help you when data is at 100%. The error arrives on insert and looks like… - [System.LimitException: Regex too complicated](https://trailassembly.com/regex-too-complicated/): Your pattern is backtracking exponentially, and the platform stopped it before it consumed the whole transaction. The message is System.LimitException: Regex too complicated, and it is almost never… - [OPERATION_TOO_LARGE](https://trailassembly.com/operation-too-large/): A single request asked the platform to touch more data than one operation is allowed to touch. Nothing is broken. Your data grew past the point where the query you wrote could be answered in one… - [INVALID_OR_NULL_FOR_RESTRICTED_PICKLIST](https://trailassembly.com/invalid-or-null-for-restricted-picklist/): You sent a value that is not in the field's value set, and the field has "Restrict picklist to the values defined in the value set" ticked. The message names the field: bad value for restricted… - [INVALID_FIELD_FOR_INSERT_UPDATE](https://trailassembly.com/invalid-field-for-insert-update/): You put a value in a field the platform will not let you write. Formula fields, roll-up summaries, most system audit fields and anything read-only for your profile all behave the same way: the write… - [Database.executeBatch cannot be called from a batch](https://trailassembly.com/executebatch-cannot-be-called-from-batch/): You called Database.executeBatch from somewhere the platform forbids it. The message lists the forbidden places explicitly, and finish() is not among them. That is the whole fix: move the call to the… - [DUPLICATE_VALUE on upsert](https://trailassembly.com/duplicate-value-on-upsert/): Your load contained two rows that resolve to the same record, or it wrote a value that a unique field already holds somewhere else. On an upsert the first case is by far the more common, and the… - [APEX_ERROR in a Bulk API job result](https://trailassembly.com/apex-error-in-bulk-api-job/): A trigger or a class it called threw an unhandled exception while your bulk load was running, and the Bulk API reported it against every row in the chunk that was being processed at the time… - [System.AssertException with no useful message](https://trailassembly.com/apex-assert-exception-message/): The assertion failed and nobody told it what to say. System.AssertException: Assertion Failed is the default message, and it appears because the assertion was written without its optional message… - [The Stub API for mocking dependencies](https://trailassembly.com/apex-stub-api-mocking/): The Stub API lets a test supply a fake implementation of a class without inserting any records. You implement System.StubProvider, call Test.createStub, and inject the result. It is the difference… - [Test data factories that survive a schema change](https://trailassembly.com/apex-test-data-factories/): Put record construction in one class so that when someone makes a field required next year, one file changes instead of forty test classes. That is the entire argument, and it is enough. The design… - [Async error handling and a retry design that leaves evidence](https://trailassembly.com/apex-async-retry-pattern/): Retries need somewhere durable to record the attempt, a decision about which failures are worth retrying, and a ceiling. A try/catch that re-enqueues itself has none of those, and it is how an org… - [Scheduled Apex and cron expressions](https://trailassembly.com/apex-scheduled-cron/): System.schedule(name, cron, instance) takes a seven-field cron expression with seconds first and no minute-level granularity below one minute. The two things that catch people are that a scheduled… - [The selector layer pattern, without the framework](https://trailassembly.com/apex-selector-pattern/): One class owns every query against one object. The payoff is not elegance — it is one file to change when a field is added, and one place where every query's security enforcement is auditable. - [Coverage without useless tests](https://trailassembly.com/apex-code-coverage/): 75% org-wide is a deployment gate, not a quality target, and it is trivially satisfied by tests that assert nothing. The useful question is not what percentage you have but whether a test would fail… - [Invocable Apex for Flow, done bulk-safe](https://trailassembly.com/invocable-apex-bulk-safe/): An @InvocableMethod receives a list, and the list is how Flow bulkifies. Writing one that takes a list, processes element zero, and returns a single result works perfectly in a screen flow and fails… - [SOQL or SOSL: when each one wins](https://trailassembly.com/soql-vs-sosl/): If you know the object and the field, SOQL. If a user typed something into a box, SOSL. The 2,000-row cap means SOSL finds things; it does not retrieve sets — and in tests it returns nothing… - [Dates, times, and time zones in Apex](https://trailassembly.com/apex-datetime-timezones/): Date has no time zone, Datetime is always stored in GMT, and every method that formats or constructs one applies the running user's time zone unless its name ends in Gmt. Nearly every time zone bug… - [Custom exceptions and an error taxonomy that helps](https://trailassembly.com/apex-custom-exceptions/): A custom exception is a class whose name ends in Exception and which extends Exception. That naming rule is enforced by the compiler and catches everyone once. The reason to define them is not… - [@TestSetup: what it saves and what it breaks](https://trailassembly.com/apex-testsetup/): @TestSetup runs once per test class and its records are rolled back to that state before each test method. It is the biggest single speed-up available in an Apex test class, and it breaks in three… - [Mocking HTTP callouts with HttpCalloutMock](https://trailassembly.com/httpcalloutmock-testing/): Apex tests cannot make HTTP callouts, so you register a mock that returns a response you construct. Test.setMock(HttpCalloutMock.class, new YourMock()) before Test.startTest(), and every callout in… - [Recursion guards, and when a static flag is the wrong fix](https://trailassembly.com/apex-recursion-guards/): A static boolean stops recursion and also stops legitimate second runs. It is the right fix for a trigger that updates its own object and the wrong fix for almost everything else, because a static… - [System.FinalException: Record is read-only](https://trailassembly.com/record-is-read-only-apex/): You tried to change something Apex will not let you change at that moment. Three different situations produce it, and the message alone does not distinguish them: writing to Trigger.new in an after… - [Too many future calls: 51](https://trailassembly.com/too-many-future-calls-51/): The limit is 50 @future calls per transaction, and you have tried to make the 51st. Verified in a scratch org on Summer '26: Limits.getLimitFutureCalls() returns 50. The cause is almost always a… - [JSON deserialization errors in Apex](https://trailassembly.com/apex-json-deserialization-errors/): The JSON does not match the shape you told Apex to expect. The message says which field and, usefully, the character position. Most of these come from one of three things: a number arriving as a… - [MALFORMED_QUERY: unexpected token](https://trailassembly.com/malformed-query-unexpected-token/): The token names the shape of the mistake. '' means the query string ran out, which is nearly always a filter built from a variable that turned out to be empty. - [Invalid conversion from runtime type](https://trailassembly.com/invalid-conversion-from-runtime-type/): You cast an Object to a type it is not. Apex checks casts at runtime, not compile time, so the code compiles fine and fails the first time the value is the wrong shape. The message names both types… - [ENTITY_IS_DELETED: the record is in the recycle bin](https://trailassembly.com/entity-is-deleted/): You hold an Id for a deleted record. Queries exclude deleted rows, so the Id came from a variable, a cache, or an external system — and ALL ROWS tells you in one query whether it is recoverable. - [REQUIRED_FIELD_MISSING, and the field that is not required on any layout](https://trailassembly.com/required-field-missing/): A field the database requires was null on insert, and the message names it in brackets. What confuses people is that the field is often not marked required on any page layout, because layout-required… - [System.ListException: List index out of bounds](https://trailassembly.com/list-index-out-of-bounds/): You asked a list for a position it does not have. The message names the index it could not reach, so List index out of bounds: 3 means you asked for element 3 of a list with fewer than four elements… - [Custom metadata, custom settings, or a constant](https://trailassembly.com/custom-metadata-vs-custom-settings/): Custom metadata types deploy with your code and do not count against SOQL limits. Custom settings do not deploy their data, and hierarchy custom settings can vary per user or profile, which metadata… - [Sharing keywords: with, without, inherited](https://trailassembly.com/apex-sharing-keywords/): With sharing respects record sharing, without sharing ignores it, and inherited sharing takes whatever the caller had. None of the three touch object permissions or field-level security. That last… - [The smallest trigger framework that works](https://trailassembly.com/apex-trigger-frameworks/): One trigger per object, no logic inside it, and a handler class that can be called directly from a test. Everything past that is preference. The frameworks people argue about solve the same three… - [Writing a Batch Apex job that survives production](https://trailassembly.com/apex-batch-that-scales/): The start method returns a QueryLocator, not a list, or you are capped at 50,000 records before you begin. Keep state out of the class unless you implement Database.Stateful, size the scope for the… - [SOQL injection in Apex, demonstrated in a real org](https://trailassembly.com/apex-soql-injection/): Bind the variable. In static SOQL that is :variable, and in dynamic SOQL it is Database.queryWithBinds. String concatenation into a query is the vulnerability, and it is not theoretical — the… - [Apex test data: one factory, @testSetup, and two hundred records](https://trailassembly.com/apex-test-data-patterns/): Build test data in one factory class, create it in @testSetup so it is inserted once per class rather than once per method, and never rely on data that happens to be in the org. The two habits that… - [Enforcing CRUD and field-level security in Apex, now that SECURITY_ENFORCED is gone](https://trailassembly.com/apex-enforcing-crud-and-fls/): Use WITH USER_MODE on your queries and AccessLevel.USER_MODE on your Database calls. The syntax most tutorials still teach, WITH SECURITY_ENFORCED, no longer compiles. Running it in a Summer '26 org… - [Future, Queueable, Batch or Scheduled: choosing the async mechanism](https://trailassembly.com/apex-choosing-async/): Pick by how much data moves and whether anything has to happen afterwards. One record and a callout: future. A chain of work, or anything needing state: queueable. More rows than one transaction can… - [One trigger per object, and the handler pattern that makes it work](https://trailassembly.com/apex-trigger-handler-pattern/): One trigger per object, no logic in the trigger body, and a handler class that the trigger calls. Not because it is tidier, but because two triggers on an object have no guaranteed order between… - [System.StringException: Invalid id, and the 15 vs 18 character problem](https://trailassembly.com/invalid-id-15-vs-18/): Stop comparing record Ids as String and compare them as Id. A 15-character Id and its 18-character form are the same record but different strings, so String comparison returns false where Id… - [SObject row was retrieved via SOQL without querying the requested field](https://trailassembly.com/soql-without-querying-field/): Add the field to the SELECT list of the query that produced the record. The exception names the object and field it wants — Contact.AccountId, Opportunity.Amount, and that field is missing from the… - [System.QueryException: List has more than 1 row for assignment to SObject](https://trailassembly.com/list-more-than-one-row/): You assigned a SOQL result straight to a single sObject variable and the query matched two or more rows. Query into a List and decide deliberately what multiple matches mean. Adding LIMIT 1 stops the… - [System.QueryException: List has no rows for assignment to SObject](https://trailassembly.com/list-has-no-rows-for-assignment/): You assigned a SOQL result straight to a single sObject variable and the query matched zero rows. Query into a List, check isEmpty(), then take element zero. The exception is not saying the query is… - [System.NullPointerException: Attempt to de-reference a null object](https://trailassembly.com/null-pointer-exception/): Something immediately to the left of a dot, a bracket, or a method call is null. Go to the class and line number in the stack trace and list every reference on that line that could be null — one of… - [CANNOT_INSERT_UPDATE_ACTIVATE_ENTITY: the wrapper that hides the real error](https://trailassembly.com/cannot-insert-update-activate-entity/): This status code is a wrapper. The real failure is a trigger, validation rule, or flow underneath it, and its message is almost always appended after the wrapper text. Read past the colon and the… - [INSUFFICIENT_ACCESS_ON_CROSS_REFERENCE_ENTITY: the parent, not the record you saved](https://trailassembly.com/insufficient-access-cross-reference/): The running user cannot access a related record (the lookup parent, the master-detail parent, the new owner) not the record you are saving. Log in as that user, open the related record by Id… - [INVALID_CROSS_REFERENCE_KEY: the Id is valid but points at nothing usable](https://trailassembly.com/invalid-cross-reference-key/): An Id you put in a lookup, master-detail, or RecordTypeId field is well-formed but points at nothing usable — wrong object type, wrong org, deleted, or an inactive record type. Take the failing Id… - [FIELD_CUSTOM_VALIDATION_EXCEPTION: finding which rule actually fired](https://trailassembly.com/field-custom-validation-exception/): Something rejected the save on purpose — a validation rule, a flow, or Apex calling addError(). The message you see is text an admin typed, not platform wording, so search your org for that exact… - [Synchronous vs asynchronous governor limits, side by side](https://trailassembly.com/sync-vs-async-limits/): Asynchronous Apex doubles your SOQL queries to 200, raises CPU time from 10,000 ms to 60,000 ms, and doubles heap to 12 MB. It changes nothing about DML statements, DML rows, query rows, or callouts… - [How to read LIMIT_USAGE_FOR_NS and prove whose code spent your limits](https://trailassembly.com/limit-usage-for-ns/): LIMIT_USAGE_FOR_NS is the block at the end of a debug log that reports governor limit consumption broken down by namespace. There is one block per namespace that executed code in the transaction… - [You have uncommitted work pending: callout ordering in Apex](https://trailassembly.com/uncommitted-work-pending/): Your transaction issued a DML statement and then tried to make an HTTP callout. Salesforce refuses, because it will not hold a database transaction open while your code waits on a server it does not… - [System.LimitException: Too many callouts: 101](https://trailassembly.com/too-many-callouts/): You have an HTTP callout inside a loop, and Salesforce allows 100 per transaction. Replace the per-record calls with one request carrying a batch payload if the remote API supports it. If it doesn't… - [System.LimitException: Apex heap size too large](https://trailassembly.com/heap-size-too-large/): Your transaction is holding more than 6 MB of data in memory at once (12 MB asynchronously). Stop materializing whole query results into a List — iterate with a SOQL for loop so only 200 records… - [System.LimitException: Too many query rows: 50001](https://trailassembly.com/query-rows-50001/): Your transaction has pulled back more than 50,000 records across all of its SOQL queries combined. Add a selective WHERE clause, replace "fetch everything and count it" with an aggregate query, or… - [System.LimitException: Too many DML rows: 10001](https://trailassembly.com/dml-rows-10001/): Your transaction is touching more than 10,000 records with DML, and no amount of bulkification fixes that — bulkification reduces the number of statements, not the number of rows. Either narrow the… - [System.LimitException: Too many DML statements: 151](https://trailassembly.com/dml-statements-151/): You have a DML statement inside a loop. Salesforce allows 150 DML statements per transaction, and the exception fires on the 151st attempt. Collect the records you want to change into a List inside… - [MIXED_DML_OPERATION: setup objects and why they cannot share a transaction](https://trailassembly.com/mixed-dml-operation/): You wrote to a setup object and a regular object in the same transaction. Salesforce does not allow that. In a test, wrap the setup-object work in System.runAs(). In production code, move one side… - [System.LimitException: Apex CPU time limit exceeded](https://trailassembly.com/cpu-time-limit/): Something in your transaction is doing per-record work that should be set-based, and the usual culprit is a nested loop. You get 10,000 ms of CPU time in a synchronous transaction and 60,000 ms… - [System.LimitException: Too many SOQL queries: 101](https://trailassembly.com/soql-101/): You have a SOQL query inside a loop. Salesforce allows 100 SOQL queries per synchronous transaction, and the exception fires when your code attempts the 101st. Move the query outside the loop… ## Flow and Automation - [Roll Back Records only works in a screen flow](https://trailassembly.com/flow-rollback-records/): The Roll Back Records element undoes every database change the flow has made so far in the current transaction, and it is available in screen flows only. An autolaunched flow or a record-triggered… - [Where a screen flow commits](https://trailassembly.com/screen-flow-transaction-boundary/): A screen flow commits its pending DML every time it shows a screen, and each segment between screens is its own transaction with its own governor limits. So a record created before a screen is… - [Bypassing automation with custom permissions](https://trailassembly.com/bypass-automation-custom-permissions/): Create a custom permission, check it in every flow's entry criteria and every trigger handler's guard, and assign it via a permission set to the integration user or the person running a data load. - [What Flow cannot do that Apex can](https://trailassembly.com/flow-vs-apex-limitations/): Flow has no Map or Set, no savepoints, no partial-success DML, no way to catch a specific exception type, and no real unit testing. Those five gaps, not performance, are what should send a… - [The automation density matrix](https://trailassembly.com/automation-density-matrix/): Count the active automations on your busiest object, and the number tells you which problem you have — under 15 is a documentation problem, 15 to 30 is a consolidation problem, and over 30 is an… - [One automation tool per object, and when to break it](https://trailassembly.com/one-tool-per-object/): Pick one automation tool per object and use it for everything on that object. Not because mixing tools is forbidden, but because the execution order between a trigger and a flow on the same object is… - [Attempt to de-reference a null object, in Flow](https://trailassembly.com/flow-null-dereference/): A flow threw "Attempt to de-reference a null object" because you used a field on a record variable that was never populated — almost always the output of a Get Records that found nothing, or a… - [Dependency sprawl: counting your downstream DML](https://trailassembly.com/downstream-dml-sprawl/): Your save is slow because one update fires automation that updates other records, which fires more automation, and nobody has counted the total. - [Flow vs quick action](https://trailassembly.com/flow-vs-quick-action/): A standard quick action is a fast, layout-driven way to create or update one record with no logic, and it is the better choice whenever that is all you need. A screen flow gives you multiple steps… - [Flow transform element](https://trailassembly.com/flow-transform-element/): The Transform element maps one collection onto another, field by field, without a Loop and without an Assignment element per field. It is the right tool when the work is pure reshaping: turning a… - [Flow testing strategy](https://trailassembly.com/flow-testing-strategy/): Flow Tests give you an automated regression net for record-triggered flows and nothing else. Everything they do not cover has to be tested somewhere, so a workable strategy has three layers: Flow… - [Flow screen component visibility](https://trailassembly.com/flow-screen-component-visibility/): Component visibility is a client-side rule on each screen component, evaluated as the user types, that decides whether the component is drawn. It does not remove the component from the flow, it does… - [Flow scheduled flows](https://trailassembly.com/flow-scheduled-flows/): A schedule-triggered flow runs on a clock you set, optionally against every record matching a filter, in system context, in batches, with nobody watching. It is the right tool for nightly… - [Flow record triggered types](https://trailassembly.com/flow-record-triggered-types/): There is one record-triggered flow with four places work can run. Before save is for setting fields on the record being saved and nothing else. After save is for touching other records, sending… - [Flow record sharing](https://trailassembly.com/flow-record-sharing/): Flow shares a record by creating a row in that object's share table, the same way Apex managed sharing does. You use a Create Records element against AccountShare, Custom_Object__Share or whichever… - [Flow record choice set](https://trailassembly.com/flow-record-choice-set/): A record choice set fills a screen component's options from records returned by a query you configure on the resource itself, and a picklist choice set fills them from the active values of a picklist… - [Flow migration from Apex](https://trailassembly.com/flow-migration-from-apex/): Move Apex to Flow when the logic is simple record manipulation that admins will need to change, and leave it in Apex when it involves volume, complex data handling, external systems, or anything that… - [Flow loops and collections](https://trailassembly.com/flow-loops-and-collections/): A Loop element costs nothing by itself. What kills a flow is putting a Get Records or an Update Records inside the loop, because each pass spends a query or a DML statement against limits that are… - [Flow in a managed package](https://trailassembly.com/flow-in-a-managed-package/): A flow shipped in a managed package is locked. Subscribers can see it, they can activate or deactivate it, and they cannot edit a single element. That is fine for logic you own and terrible for… - [Flow http callout action](https://trailassembly.com/flow-http-callout-action/): The HTTP Callout action lets you define a REST call in Flow Builder by pasting a sample response, which Salesforce turns into a typed data structure you can reference like any other flow resource… - [Flow entry criteria formula](https://trailassembly.com/flow-entry-criteria-formula/): Switch a record-triggered flow's entry criteria to a formula when the condition builder cannot express what you need, which in practice means mixed AND and OR logic across different fields, a… - [Flow custom error messages](https://trailassembly.com/flow-custom-error-messages/): The Custom Error element stops a save and shows the user a message you wrote, rolling back everything in the transaction. It does what a validation rule does, with the whole flow available to work… - [Flow async path](https://trailassembly.com/flow-async-path/): The asynchronous path is a branch of an after-save record-triggered flow that runs in its own transaction once the original one has committed, which buys you a fresh set of governor limits, the… - [Flow assignment element](https://trailassembly.com/flow-assignment-element/): Assignment sets values on variables in memory and touches the database not at all. Use Equals to overwrite a value, Add to append an item to a collection or to sum a number, and a run of Equals rows… - [Approval processes: steps, locks and recall](https://trailassembly.com/salesforce-approval-processes/): An approval process is entry criteria, an ordered list of steps, an approver for each step, and three sets of actions that fire on submission, approval and rejection. Almost everything that goes… - [Profiling flow performance](https://trailassembly.com/flow-performance-profiling/): The Flow Builder debug panel tells you what ran, not how long it took. For timing you need a debug log with the Workflow category set to FINER or FINEST, which produces FLOW_ELEMENT_BEGIN and… - [Naming and documenting flows](https://trailassembly.com/flow-naming-and-documentation/): The flow label is the only documentation most people will ever read, because the Setup list shows labels and hides descriptions. Put the object, the trigger type, and the purpose in the label, in… - [Launching an autolaunched flow from Apex](https://trailassembly.com/call-flow-from-apex/): Instantiate Flow.Interview.Your_Flow_API_Name with a map of inputs, call start(), and read results with getVariableValue(). Only autolaunched flows work. Apex cannot run a screen flow because there… - [Paused and failed flow interviews](https://trailassembly.com/paused-and-failed-flow-interviews/): Setup, Paused and Failed Flow Interviews. Paused interviews are waiting on a Pause element and can be resumed. Failed interviews hit an unhandled fault and cannot be resumed, only deleted. Both hold… - [Sending email from Flow](https://trailassembly.com/flow-send-email/): The core Send Email action is for a subject and body you build in the flow. An Email Alert is for a Classic email template with merge fields, and it is the route to take when marketing owns the… - [File upload in a screen flow](https://trailassembly.com/flow-screen-file-upload/): The File Upload component returns a collection of ContentDocument Ids, and the file is uploaded the moment the user picks it, before they click Next. Set Related Record ID on the component if you… - [Flow Orchestration: what it is for](https://trailassembly.com/flow-orchestration/): Flow Orchestration co-ordinates work across several people over hours or days. It groups flows into stages and steps, hands interactive steps to users or queues as work items, and runs each step in… - [Multi-select picklists in Flow](https://trailassembly.com/flow-multi-select-picklists/): A multi-select picklist is one text value with semicolons between the selections, not a list. Decision conditions see that string, so Contains matches substrings and Equals only matches when the user… - [Flow formula problems, and why it works in a field](https://trailassembly.com/flow-formula-gotchas/): Flow formulas look like field formulas and are not the same engine. There is no "treat blank fields as zeroes" setting, so null poisons arithmetic silently. Relationship traversal works off $Record… - [Error handling for integration flows](https://trailassembly.com/flow-error-handling-for-integrations/): Connect a fault path to every callout element, capture {!$Flow.FaultMessage}, and publish a platform event to record the failure rather than creating a log record directly. A log record created on… - [Deleting records in Flow without regret](https://trailassembly.com/flow-delete-records/): The Delete Records element has two modes, and the dangerous one is "Specify conditions". There is no confirmation dialog, no preview of what will match, and no dry run. Records go to the Recycle Bin… - [Decision elements or formula resources](https://trailassembly.com/flow-decision-vs-formula/): Put the branch in a Decision, put the calculation in a formula. A Decision draws the fork on the canvas where the next person can see it. A formula resource hides its logic inside a resource nobody… - [Debug against Run, and why they differ](https://trailassembly.com/flow-debug-vs-run/): Debug runs the flow inside Flow Builder with a details panel showing every element, every variable value, and the outcome each Decision took. Run launches the flow the way a user would, with no… - [Updating related records in Flow](https://trailassembly.com/flow-cross-object-updates/): There are three ways to update related records in Flow, and the first one is usually right. Update Records with "Specify conditions to identify records" does the query and the update in one element… - [A required field error, seen from Flow](https://trailassembly.com/required-field-missing-on-flow/): A flow tried to create or update a record without a value the object requires, and with no fault connector on the element the whole interview stopped. The error email carries the real message, buried… - [Flow Tests: what they cover and what they miss](https://trailassembly.com/flow-tests-what-they-cover/): Flow Tests cover record-triggered flows only, assert only on the triggering record, and contribute nothing to Apex code coverage. Within that narrow box they are genuinely useful for catching a… - [Screen flow validation that works](https://trailassembly.com/screen-flow-validation/): Every input component on a screen has a Validate Input section holding a formula that must evaluate to true, plus the error message shown when it does not. It fires when the user clicks Next or… - [Platform-event-triggered flows](https://trailassembly.com/platform-event-triggered-flows/): A platform event-triggered flow runs as the Automated Process user, with no running user, no record context, and nobody to show an error to. Every design decision follows from those three facts. If… - [Migrating Process Builder to Flow](https://trailassembly.com/migrate-process-builder-to-flow/): Use Setup, Migrate to Flow to convert each process, then rebuild what it produces rather than shipping it. The tool gets the logic across accurately and the design badly, and the thing that will… - [Passing variables to a subflow](https://trailassembly.com/flow-subflow-variables/): A variable only crosses the boundary if the subflow's variable has Available for input or Available for output ticked, and the parent only sees those checkboxes on the active version of the subflow… - [Reactive screen components in Flow](https://trailassembly.com/flow-reactive-screen-components/): Reactive screen components let one component on a screen respond to another component on the same screen while the user is still on it. No Next click, no second screen, no round trip. What it… - [Get Records: filter, sort, and what happens with no results](https://trailassembly.com/flow-get-records-behaviour/): When a Get Records element finds nothing, the variable is set to null, not to an empty collection. Test it with Is Null equals True in a Decision before anything downstream touches it. And turn off… - [Collection Filter and Collection Sort](https://trailassembly.com/flow-collection-filter-and-sort/): Collection Filter and Collection Sort work on a collection you already have in memory. Neither one issues a query, so neither one costs you a SOQL statement. If you are about to add a second Get… - [Approval process or flow](https://trailassembly.com/approval-process-vs-flow/): Approval processes give you three things flow does not: automatic record locking, delegated approvers, and a queryable approval history. If you need any of those, use an approval process and drive it… - [Migrating Workflow Rules to Flow](https://trailassembly.com/migrate-workflow-rules/): Same-record field updates in a workflow rule force a second save with every update trigger firing again; a before-save flow does not. Maps each workflow action to its flow equivalent, lists what the… - [Flow limits: elements, SOQL, DML, and the ones that actually bite](https://trailassembly.com/flow-limits/): Flows do not get their own governor budget. A flow runs inside the same transaction as everything else on the save, drawing from the same 100 SOQL queries, 150 DML statements, 10,000 DML rows, and… - [Roll-ups without a roll-up summary field](https://trailassembly.com/flow-rollup-without-master-detail/): If the relationship can be master-detail, convert it and use a real roll-up summary field — the platform then maintains the number on every event, including restores, which no automation you write… - [HTTP callouts from Flow with External Services](https://trailassembly.com/flow-http-callout/): How the HTTP Callout action, External Services, and named credentials fit together, and why a record-triggered flow cannot call out on its synchronous path. The asynchronous path, what eventual… - [Calling Apex from Flow safely](https://trailassembly.com/flow-call-apex/): Mark a static method @InvocableMethod, give it exactly one parameter that is a List, and return a List holding one entry per input entry, in the same order. Flow batches records into a single call… - [Flow scheduled paths: every gotcha](https://trailassembly.com/flow-scheduled-paths/): A scheduled path is a separate transaction that runs later with a fresh set of governor limits. What it is not is a job running as the Automated Process user. Salesforce documents that scheduled… - [How to read a flow error email](https://trailassembly.com/flow-error-email/): Two parts of that email matter. The line at the top naming the element that failed and the error it threw, and the interview details block below it listing every element the flow ran with the values… - [Flow fault paths, done properly](https://trailassembly.com/flow-fault-paths/): Put a fault path on every element that touches the database, and make each one end somewhere a human or a record will actually see. A fault path routed to a bare End element is the worst of your… - [Before-save vs after-save flows: the decision and what each costs](https://trailassembly.com/before-save-vs-after-save/): A before-save flow can only set fields on the triggering record, and every other difference follows from that. Row-by-row comparison, a step-by-step conversion from Update Records to an Assignment on… - [Your record-triggered flow is not firing: a diagnostic checklist](https://trailassembly.com/flow-not-firing/): Almost always one of three things — the version you edited is not the version that is active, the entry conditions never evaluate true for your record, or the trigger type does not match the… - [System context vs user context in Flow](https://trailassembly.com/flow-system-vs-user-context/): Record-triggered flows already run in system context without sharing — they can read and write every record in the org regardless of who saved the record. Screen flows run in user context by… - [Five flows on one object: consolidating without breaking anything](https://trailassembly.com/consolidating-flows/): Five flows on one object is not five small problems, it is one ordering problem you cannot see. Consolidate them, but do it in stages — inventory, map every write, find the overlaps, build the… - [Controlling order when Flow and Apex share an object](https://trailassembly.com/flow-and-trigger-order/): You cannot order a flow against an Apex trigger at all, and you can only order flows against other flows on the same object with the same timing. What you can rely on is the documented save order —… - [Flow or Apex trigger: the actual decision](https://trailassembly.com/flow-vs-apex-trigger/): Put same-record field logic in a before-save record-triggered flow, and write Apex the moment the requirement involves real branching, recursion control, callout orchestration, logic you need to… - [ISCHANGED equivalents in Flow](https://trailassembly.com/flow-ischanged/): Flow does have ISCHANGED — record-triggered flows support ISCHANGED, ISNEW, and PRIORVALUE in formulas, with $Record in place of the object name. There is also an Is Changed operator you can pick… - [$Record vs $Record__Prior, and where each is available](https://trailassembly.com/flow-record-prior/): $Record holds the record as it is being saved. $Record__Prior holds the same record's field values from immediately before that save. It exists only in a record-triggered flow that can be triggered… - [Loops in Flow, and when not to use one](https://trailassembly.com/flow-loops/): A Loop is only justified when you need to do something different to each record individually. If you are filtering a collection, sorting it, taking the top few, or finding one record, a Collection… - [Bulkification in Flow: loops, DML, and the limits you will hit](https://trailassembly.com/flow-bulkification/): Flow groups operations across interviews automatically but bulkifies nothing inside a Loop. What 200 records costs with a DML in the loop versus the collection pattern, the shared limits it spends… - [Flow entry conditions and the setting that stops duplicate runs](https://trailassembly.com/flow-entry-conditions/): Entry conditions decide which records get into the flow, but the setting that stops the flow running over and over sits directly underneath them. It is When to Run the Flow for Updated Records, and… - [CANNOT_EXECUTE_FLOW_TRIGGER: a flow failed and took the save with it](https://trailassembly.com/cannot-execute-flow-trigger/): A record-triggered flow on the object failed, and because it ran in the save transaction it took the whole DML down with it. Find the flow error email (it names the element that failed and its input… - [Why your record-triggered flow runs twice](https://trailassembly.com/flow-runs-twice/): Your after-save flow updates the record that triggered it. That second update starts another save on the same record, and the save order runs again, firing your automation a second time. Move… ## Data and Integration - [A rolled-back transaction still delivers the event](https://trailassembly.com/platform-event-publish-behavior/): A platform event defined with publishBehavior set to PublishImmediately is delivered the moment you call EventBus.publish, and rolling the publishing transaction back does not recall it. Subscribers… - [Apex merge keeps every master field, blanks included](https://trailassembly.com/merging-duplicate-records/): An Apex merge keeps the master record's value for every field, blank ones included, and a single merge can involve at most three records in total. Neither matches what the merge wizard in the UI… - [Webhook outbound](https://trailassembly.com/salesforce-webhook-outbound/): Use an Apex callout when you need control over the payload, the headers and the signature, which is nearly always. Use a platform event as the trigger for that callout rather than firing it from the… - [Extracting millions of records](https://trailassembly.com/query-api-large-extracts/): Use Bulk API 2.0 query jobs for anything over about a hundred thousand records. It chunks server-side, returns results as CSV you stream, and costs a handful of API requests instead of thousands… - [Salesforce to Salesforce](https://trailassembly.com/salesforce-to-salesforce/): Salesforce to Salesforce is a native feature for sharing records between two separate Salesforce orgs by connection, without an integration. It works, it is old, and it has real constraints —… - [Middleware or point to point](https://trailassembly.com/middleware-vs-point-to-point/): Go point to point until you have three integrations, then put middleware in before the fourth. The threshold is not about complexity, it is about connection count — point-to-point links grow faster… - [What the weekly export actually gives you](https://trailassembly.com/salesforce-weekly-export/): The weekly export gives you a set of zipped CSV files containing your record data, and nothing else. No metadata, no relationships you can restore without work, no way to get back to a particular… - [The Recycle Bin: fifteen days and a capacity cap](https://trailassembly.com/salesforce-recycle-bin/): Deleted records sit in the recycle bin for fifteen days, still counting against your data storage, and after that they are gone. The bin has a capacity tied to your storage allowance, so a large… - [Migrating Notes and Attachments to Files](https://trailassembly.com/salesforce-notes-and-attachments-migration/): Migrating classic Notes and Attachments to Enhanced Notes and Files is a data migration wearing the costume of a settings change, and the two things that catch people are dates and sharing. The free… - [Mass Transfer Records, and when to stop using it](https://trailassembly.com/salesforce-mass-transfer-records/): Setup has a Mass Transfer Records tool for accounts, leads and custom objects, and it is fine for hundreds of records and wrong for hundreds of thousands. Ownership is not a field like any other… - [Writing a data retention policy that holds up](https://trailassembly.com/salesforce-data-retention-policy/): A retention policy names each category of data, says how long it is kept, says what happens at the end, and produces a record proving it happened. Salesforce gives you the mechanisms to delete and… - [Streaming vs polling](https://trailassembly.com/salesforce-streaming-vs-polling/): Streaming wins on latency and on API cost, polling wins on simplicity and on being able to prove you saw everything. The real comparison is not push against pull, it is whether your consumer can hold… - [Where the SOAP API is still required](https://trailassembly.com/salesforce-soap-api-still/): The SOAP API is not deprecated, it is not frozen, and there are several things in Salesforce you simply cannot do without it. The Metadata API is SOAP. Outbound messages are SOAP. Apex webservice… - [Heroku integration](https://trailassembly.com/salesforce-heroku-integration/): Heroku Connect keeps a Postgres database in step with a set of Salesforce objects, in one direction or both, and it is the right answer when your application needs to query Salesforce data the way… - [Error response design](https://trailassembly.com/salesforce-error-response-design/): A good error response tells the caller three things, which are whether to retry, what to fix, and what to quote when they raise a ticket. Status code for the category, a stable machine-readable code… - [Connected app policies](https://trailassembly.com/salesforce-connected-app-policies/): The OAuth settings on a connected app decide who can authorise it, the scopes decide what the resulting token can reach, and the policies decide how long that token survives and from where it works… - [Api versioning](https://trailassembly.com/salesforce-api-versioning/): An API version is a frozen contract. The version number in your request URL, your WSDL or your Apex class metadata decides which fields exist, which behaviours apply and which bugs you still get… - [Api pagination](https://trailassembly.com/salesforce-api-pagination/): The REST query endpoint returns up to 2,000 records and a nextRecordsUrl you follow until done is true. SOAP does the same through queryMore with a locator. That mechanism is fine for reading a… - [Integration user design](https://trailassembly.com/integration-user-design/): Give every integration its own user, on an integration licence where you can, with a profile that grants almost nothing, permission sets that grant exactly what that integration touches, login IP… - [Integration testing strategy](https://trailassembly.com/integration-testing-strategy/): Apex mocks prove your code handles a response correctly, sandbox runs against a real endpoint prove the connection works, and contract tests prove the other side has not changed its mind. They catch… - [Handling API rate limits in a client](https://trailassembly.com/handling-api-rate-limits/): Read the Sforce-Limit-Info header on every response, cap your own concurrency before Salesforce caps it for you, and retry with exponential backoff and jitter only on the errors that are worth… - [External Services and OpenAPI](https://trailassembly.com/external-services-and-openapi/): External Services takes an OpenAPI description of somebody else's REST service and generates invocable actions you can drop into Flow without writing Apex. It works well for small, well-behaved APIs… - [Data Cloud, for Salesforce people](https://trailassembly.com/data-cloud-basics/): Data Cloud is a separate data platform bolted onto your org, not a set of custom objects. It ingests data from many systems, maps it into a shared model, works out which records across those systems… - [The Bulk API 2.0 job lifecycle](https://trailassembly.com/bulk-api-2-job-lifecycle/): Create the job, upload the CSV, tell Salesforce you are done, poll until the state stops changing, then download three result files. Five calls, and the only one that takes any real time is the… - [Record locking, and the parents you never mentioned](https://trailassembly.com/salesforce-record-locking/): Salesforce locks a record for the duration of the transaction that is writing to it, and it locks some records you never mentioned, above all the master in a master-detail relationship. A second… - [Record IDs: 15, 18 and key prefixes](https://trailassembly.com/salesforce-record-id-behaviour/): Every Salesforce record has a 15-character case-sensitive ID and an 18-character case-insensitive version of the same ID, differing only by a three-character suffix. The first three characters… - [The Pub/Sub API, and replaying events](https://trailassembly.com/salesforce-pub-sub-api/): The Pub/Sub API is a gRPC service that lets an external system publish and subscribe to Salesforce events over a single long-lived connection, with binary Avro payloads and explicit flow control. It… - [Designing a platform event schema](https://trailassembly.com/salesforce-platform-events-schema/): A platform event is a published contract, not a custom object you can tidy up later. Subscribers compile against its shape, published events cannot be recalled, and there is no versioning mechanism… - [Outbound messages, and what to replace them with](https://trailassembly.com/salesforce-outbound-messages/): An outbound message is a SOAP call Salesforce sends to a URL you nominate when a record meets a condition, configured entirely in Setup with no code. They are legacy because they were built for… - [The GraphQL API, and how it differs from REST](https://trailassembly.com/salesforce-graphql-api/): The Salesforce GraphQL API gives you a single endpoint where the client states exactly which fields and related records it wants and gets back that shape, instead of a URL per object. It sits on top… - [File upload limits and behaviour](https://trailassembly.com/salesforce-file-upload-limits/): The ceiling depends entirely on which mechanism you use. Salesforce Files, stored as ContentVersion, allow far larger files than the old Attachment object, which is capped in the low tens of… - [Running a data quality programme](https://trailassembly.com/salesforce-data-quality-programme/): A data quality programme is three things running at the same time. A small set of measures published on a schedule, a named person in the business who owns each measure, and controls at the point of… - [Masking data in a sandbox](https://trailassembly.com/salesforce-data-masking/): A sandbox refreshed from production contains real customer data with weaker controls and more people in it, so the data must be altered before anyone uses the sandbox, and Salesforce Data Mask is the… - [The Composite API](https://trailassembly.com/salesforce-composite-api/): The Composite API lets you send several REST requests in a single HTTP round trip, optionally as one all-or-nothing transaction, with later subrequests able to reference IDs and fields returned by… - [Address data, and why it degrades](https://trailassembly.com/salesforce-address-standardisation/): Address data degrades because Salesforce ships address fields as free text and every source writes them differently. You have three options: verify at entry with a third-party service, normalise in a… - [Middleware or native Salesforce integration](https://trailassembly.com/mulesoft-vs-native-integration/): Build it natively in Salesforce when the integration is point to point, low volume, and owned by the Salesforce team. Buy middleware when you have several systems that all need to talk to each other… - [Monitoring integrations properly](https://trailassembly.com/integration-error-monitoring/): Log every integration call with a correlation ID, the interface name, the outcome and the duration, but never the raw payload. Alert on error rate over a window rather than on individual failures… - [Deleting data safely at scale](https://trailassembly.com/deleting-data-safely/): A normal delete is reversible for a limited window because the record sits in the recycle bin keeping its ID. A hard delete is not reversible by you at all. At scale the danger is rarely the delete… - [Authenticating outbound callouts](https://trailassembly.com/apex-callout-authentication-patterns/): Use a Named Credential paired with an External Credential for every outbound callout, and never put a secret in Apex, a custom setting or a custom metadata record. The platform then handles token… - [OAuth scopes, and the least-privilege set](https://trailassembly.com/oauth-scopes-least-privilege/): Most integrations need api and nothing else. Add refresh_token only if your flow issues one, and identity scopes only if you consume the identity endpoint. full is the default on a large number of… - [External Client Apps against Connected Apps](https://trailassembly.com/external-client-apps/): External Client Apps are the replacement for Connected Apps. They run the same OAuth flows against the same endpoints, so nothing your client code does needs to change. Build new integrations on… - [What Salesforce backup does and does not cover](https://trailassembly.com/what-backup-does-not-cover/): The weekly data export gives you CSVs of your records and nothing else. It does not cover your metadata, it does not preserve relationships in a form you can reload, and it is not a restore. A real… - [Time zones in data loads](https://trailassembly.com/time-zones-in-data-loads/): Date/Time values are stored in UTC, and a value in your CSV without an explicit offset gets interpreted in whatever time zone the loading tool thinks it is in, then converted. Get that wrong and… - [Sorting your load file by parent Id](https://trailassembly.com/sorting-load-files-by-parent/): Sort your CSV by the parent ID before loading. Bulk API splits the file into chunks and processes them in parallel, and two chunks holding children of the same parent will both try to lock that… - [Seeding a sandbox with usable data](https://trailassembly.com/seeding-a-sandbox-with-data/): Pick the sandbox type by what the data is for, use a sandbox template so the copy is a coherent slice rather than a random sample, mask anything personal before a human logs in, and load in… - [An archiving strategy that survives audit](https://trailassembly.com/salesforce-archiving-strategy/): An archive that survives an audit needs three things a storage-reduction exercise does not: a written retention rule, evidence that the rule was applied, and a retrieval you have actually performed… - [REST, SOAP, Bulk or Streaming: choosing an API](https://trailassembly.com/rest-soap-bulk-streaming/): REST for almost everything, SOAP only when the other side insists on a WSDL, Bulk once you are past roughly 50,000 records, and Streaming when you want Salesforce to tell you instead of you asking… - [Receiving webhooks with Apex REST](https://trailassembly.com/receiving-webhooks-with-apex-rest/): Expose an Apex REST endpoint, verify the caller's signature yourself, write the raw payload to a staging record, enqueue the real work, and return 200 in well under a second. Everything that goes… - [Salesforce Connect, external objects and OData](https://trailassembly.com/external-objects-and-odata/): Salesforce Connect lets you see data that lives somewhere else without copying it, and the price is that the data behaves like a read-mostly guest. No triggers, no roll-up summaries, no field… - [Designing external IDs before you migrate](https://trailassembly.com/designing-external-ids/): Before you migrate anything, give every object one external ID field holding the key from the source system, mark it unique, and load with upsert instead of insert. That single decision is what makes… - [Converting lookup to master-detail, and back](https://trailassembly.com/converting-lookup-to-master-detail/): You can convert a lookup to master-detail only if every single child record has that lookup populated, and you can convert back only if you first delete every roll-up summary field that depends on… - [Changing picklist values when records use them](https://trailassembly.com/changing-picklist-values-in-use/): Deactivating a value hides it from the dropdown and leaves it on every record that already has it. Deleting asks you whether to replace it, and the replacement runs as a background job that rewrites… - [Change Data Capture in practice](https://trailassembly.com/change-data-capture-in-practice/): Change Data Capture publishes a near-real-time event whenever a record is created, updated, deleted or undeleted, and the event carries only the fields that changed plus a header describing the… - [OAuth flows compared: web server, JWT, client credentials](https://trailassembly.com/salesforce-oauth-flows-compared/): Pick by who is present. A person clicking a button gets Web Server flow. A server with no person gets JWT Bearer or Client Credentials. A device with no browser gets Device flow. Username-Password… - [Monitoring API consumption before you hit the wall](https://trailassembly.com/salesforce-api-limits-monitoring/): The daily API request limit is calculated from your edition and licence count, it resets on a rolling 24-hour window rather than at midnight, and the first warning most orgs get is an integration… - [Platform Event publishing and delivery limits](https://trailassembly.com/platform-events-publishing-limits/): Publishing is limited by a daily allowance based on your edition and by a per-transaction cap on how many events one transaction can publish. Delivery is limited separately, and the limit that… - [Files, Attachments and Documents: which to migrate to](https://trailassembly.com/files-vs-attachments/): Files (ContentDocument) is the current model, Attachments and Documents are the legacy ones, and new work should use Files exclusively. The migration matters because Attachments cannot be shared to… - [Changing a field type on populated data](https://trailassembly.com/changing-field-type-on-populated-data/): Some field type changes are lossless, some truncate data silently, and some are refused outright. Salesforce warns you generically and does not tell you which rows will be affected, so the work is… - [Designing an Apex REST endpoint](https://trailassembly.com/apex-rest-endpoint-design/): @RestResource gives you a URL under /services/apexrest/ and six annotations for the HTTP verbs. The class must be global, the methods static, and the URL mapping unique. Everything after that is… - [System.CalloutException: Read timed out](https://trailassembly.com/callout-read-timed-out/): Your HTTP callout waited and gave up. The default timeout in Apex is 10 seconds, the maximum you can set is 120 seconds, and the transaction has a hard ceiling of 120 seconds of cumulative callout… - [Data Loader or Bulk API 2.0](https://trailassembly.com/data-loader-vs-bulk-api/): Data Loader is a client, Bulk API 2.0 is what it can talk to. So the real question is not "which one" but "which API should this load use", and the answer is volume: under about 50,000 records the… - [Named Credentials, end to end](https://trailassembly.com/named-credentials-end-to-end/): A Named Credential holds the endpoint and the authentication, so your Apex holds neither. The callout becomes callout:My_Service/path and the platform attaches the credentials. That is worth doing… - [Upsert on an external ID, correctly](https://trailassembly.com/upsert-with-external-ids/): Upsert matches on one field you nominate, and everything that goes wrong with it comes from that field being a worse key than you thought. Blank values, values that repeat, values that differ only in… - [The order you load objects in decides how much of the migration you redo](https://trailassembly.com/data-migration-object-order/): Load in dependency order, and the order is decided by your relationships, not by your project plan. Users and roles first, because ownership and access depend on them. Then parents before children… - [Design the retry before you write the callout](https://trailassembly.com/callout-retries-and-idempotency/): Your callout will run twice. Not because of a bug — because a timeout tells you nothing about whether the other system did the work, and somebody will replay the message anyway. Design for that on… - [Change Data Capture, Platform Events, or an outbound message](https://trailassembly.com/platform-events-vs-cdc/): Change Data Capture is for "tell me when a record changed", and you get no say in the payload. Platform Events are for "tell me when this business thing happened", and you define the payload… ## Architecture - [Most Salesforce clouds are one org with a different licence](https://trailassembly.com/salesforce-clouds-explained/): A cloud is a pricing package, not an architecture. Sales, Service, Revenue, Field Service and Experience Cloud are licences and permission sets on the org you already have. Marketing Cloud… - [Business capability maps for a Salesforce programme](https://trailassembly.com/business-capability-map/): A capability map lists what the business does, not how it does it or which system does it. "Manage customer credit" is a capability; "run the credit check flow in Salesforce" is not. It earns its… - [Drawing a system landscape diagram that survives review](https://trailassembly.com/system-landscape-diagram/): A system landscape diagram shows which systems exist, who owns them, and what moves between them — and nothing else. It survives review when every arrow is labelled with its payload and frequency… - [The kit of parts for Salesforce diagrams](https://trailassembly.com/diagram-kit-of-parts/): Agree a fixed set of shapes before anybody draws anything, because most Salesforce diagrams fail review not from bad thinking but from every box looking the same. A workable kit is six shapes, three… - [RTO and RPO on a platform you do not control](https://trailassembly.com/rto-and-rpo/): Write down how much data you can afford to lose (RPO) and how long you can afford to be without the system (RTO), then check whether anything you currently have can meet those numbers. - [When not to use event-driven architecture](https://trailassembly.com/when-not-to-use-event-driven/): Do not use platform events when the publisher needs to know the outcome, when ordering matters, when the work must be transactional with the save, or when you have one subscriber that will always be… - [The search index is not the database](https://trailassembly.com/search-index-is-not-the-database/): SOSL and global search read a search index that is built asynchronously after a record is saved, so a record can exist, be queryable by SOQL, and still not appear in search for a short period… - [Batch concurrency, and the state bug it causes](https://trailassembly.com/batch-concurrency-five-threads/): Batch Apex chunks can run concurrently, and "concurrently" tops out at five jobs per org rather than five chunks of your job. Within one batch job the chunks are processed in an order you do not… - [Why your batch job is late: the async queue](https://trailassembly.com/async-queue-flow-control/): Your batch job is not broken, it is queued. Salesforce runs asynchronous Apex through a shared queue with a concurrency ceiling, and when the instance is busy or your org has too much queued work… - [The daily async Apex limit](https://trailassembly.com/daily-async-apex-limit/): Your org gets 250,000 asynchronous Apex executions per rolling 24 hours, or 200 times your user licence count, whichever is higher. Batch Apex counts one execution per execute chunk rather than one… - [How Salesforce actually stores your data](https://trailassembly.com/multitenant-data-model/): Your custom object is not a table and your custom field is not a column. Salesforce stores every org's records in a small number of shared structures, describes your schema in metadata rather than in… - [The four ways Salesforce runs your query](https://trailassembly.com/salesforce-query-optimizer/): Salesforce does not run your SOQL against your data directly. A cost-based optimiser rewrites it against a shared multi-tenant schema, and it picks one of four strategies — an index on your filter… - [Working with business users](https://trailassembly.com/salesforce-working-with-business-users/): People bring you solutions, not requirements, and your job is to walk backwards from the solution to the problem without making anyone feel interrogated. "Can you add a checkbox to the Opportunity"… - [Estimating as a team](https://trailassembly.com/salesforce-estimating-as-a-team/): Estimate relatively, estimate as a group, and treat disagreement as the most valuable output of the session. When two people size the same item at 2 and 13, one of them knows something the other does… - [Big objects, and what you give up](https://trailassembly.com/salesforce-big-objects/): A big object stores billions of rows cheaply and gives up almost everything else. No triggers, no validation rules, no sharing rules, no ordinary page layouts, and queries only along an index you… - [Skinny tables: what they are and how to get one](https://trailassembly.com/skinny-tables/): A skinny table is a copy of the fields you query most, stored without the joins the standard structure requires, built and maintained by Salesforce at your request. It makes big reports and list… - [Well-Architected: security in practice](https://trailassembly.com/salesforce-well-architected-security/): Security on Salesforce is four independent layers, and an org is only as strong as the weakest one that an attacker or a mistake actually touches. Most reviews spend their time on the layer that is… - [Well-Architected: reliability in practice](https://trailassembly.com/salesforce-well-architected-reliability/): Reliability on a platform you do not operate means designing for the failures you can still cause, which is most of them. You are not responsible for the data centre. You are responsible for the… - [Well-Architected: composability](https://trailassembly.com/salesforce-well-architected-composability/): Composability means each part of the org can be understood, changed and replaced without knowing about the others. On Salesforce the enemy is not bad code, it is accumulated implicit coupling: the… - [Paying down technical debt, sustainably](https://trailassembly.com/salesforce-technical-debt-paydown/): Technical debt gets paid down when it is attached to work someone already wants done, and not otherwise. A dedicated cleanup sprint gets cancelled the first time a deadline moves. The durable method… - [Sharing recalculation at scale](https://trailassembly.com/salesforce-sharing-recalculation/): Sharing recalculation is the platform rebuilding the rows that record who can see what. It runs when you change something structural, it can take hours on a large org, and while it runs you may see… - [Security Health Check and Salesforce Optimizer](https://trailassembly.com/salesforce-optimizer-and-health-check/): Security Health Check scores your org's security settings against a baseline and takes a minute to read. Salesforce Optimizer reports on configuration debt and takes an afternoon to act on. Both are… - [Hyperforce and data residency](https://trailassembly.com/salesforce-hyperforce-data-residency/): Hyperforce is Salesforce running on public cloud infrastructure instead of their own data centres, and the part that matters to you is that it lets your org live in a specific country. Most of the… - [Requesting a custom index, and what cannot be indexed](https://trailassembly.com/requesting-a-custom-index/): You cannot create a custom index yourself. You open a case with Salesforce Support, show them the query and the selectivity, and they add it. The exception is that external ID and unique fields get… - [Experience Cloud site performance](https://trailassembly.com/experience-cloud-site-performance/): Most slow Experience Cloud sites are slow for one of three reasons. The template is an Aura one when it could be LWR, the home page fires a separate Apex call for every component on it, or nobody has… - [Account hierarchies, and reporting across a tree](https://trailassembly.com/account-hierarchies/): An account hierarchy is one self-lookup field, ParentId, and a viewer button. There are no roll-ups up the tree, no reporting across a whole tree, and no sharing implied by the relationship… - [When the answer is not Salesforce](https://trailassembly.com/when-not-to-use-salesforce/): Salesforce is a poor fit when the work is high-volume machine-to-machine processing, when the data has no relationship to a customer or a sales process, when you need sub-second guaranteed latency… - [Estimating a Salesforce build honestly](https://trailassembly.com/salesforce-project-estimation/): Estimate the parts nobody demonstrates. The build is usually the smallest line. Data migration, integration, testing, permissions, training and the decisions waiting on someone else routinely exceed… - [Naming conventions that survive five years](https://trailassembly.com/salesforce-naming-conventions/): The API name is permanent in practice, so the convention that matters is the one for API names. Labels can be renamed freely and are therefore the wrong place to encode meaning. Most naming arguments… - [A governance model that does not become a bottleneck](https://trailassembly.com/salesforce-governance-model/): Governance fails in one of two directions, and the failure mode tells you which correction you need. Too little and the org accumulates changes nobody can explain. Too much and people build outside… - [Documentation that survives handover](https://trailassembly.com/salesforce-documentation-handover/): Document the things the org cannot tell you itself. Field lists, flow diagrams and object models are already in Setup and any document describing them is stale the week it is written. What is not in… - [Capacity planning for API, storage and async](https://trailassembly.com/salesforce-capacity-planning/): Four things run out on Salesforce, and they run out on different schedules. Data storage grows slowly and predictably. File storage grows faster than anyone models. API calls spike with an… - [Buy or build on the AppExchange](https://trailassembly.com/buy-vs-build-appexchange/): Buy when the problem is genuinely generic and someone else maintains it through every release. Build when the problem is how your business specifically works. The deciding question is not cost, it is… - [Architecture decision records for Salesforce projects](https://trailassembly.com/architecture-decision-records/): An architecture decision record is one page saying what you decided, what you considered, and why. On a Salesforce project it earns its keep more than on most, because so many platform decisions are… - [Person accounts: the switch you cannot undo](https://trailassembly.com/person-accounts-the-one-way-door/): Enabling person accounts cannot be undone. Not by you, not by Salesforce support, not by a data fix. It permanently changes the Account object, makes record types mandatory on Account, doubles your… - [Why your query got slow at two million rows](https://trailassembly.com/why-your-query-got-slow/): Your query did not get slow, your data got big. A filter that matched 40,000 rows out of 300,000 was selective enough to use an index. The same filter matching 800,000 rows out of two million is not… - [Trigger design that still works at volume](https://trailassembly.com/trigger-design-at-volume/): Write every trigger as though it will always receive 200 records, because eventually it will. That means no SOQL inside a loop, no DML inside a loop, one handler per object, and a hard decision about… - [Standard object or custom object](https://trailassembly.com/standard-vs-custom-object/): Use the standard object when the thing you are modelling is what Salesforce means by that object, even if two thirds of its fields are useless to you. Build a custom object when the standard one… - [Taking a technical debt inventory](https://trailassembly.com/salesforce-technical-debt-inventory/): Run the inventory as a query-driven audit you can repeat in an afternoon, not a spreadsheet nobody updates. Count six things: fields with no data and no references, inactive and duplicate automation… - [The Query Plan tool, read properly](https://trailassembly.com/salesforce-query-plan-tool/): The Query Plan tool shows you which index the optimiser would use, and a cost number where anything above 1.0 means no index is being used well. It lives in the Developer Console behind a setting you… - [Ownership skew, explained by its symptoms](https://trailassembly.com/salesforce-ownership-skew/): Ownership skew is one user owning more than about 10,000 records of an object. It costs you nothing day to day and a great deal at the moment something changes that user's position (a role change, a… - [Backup and disaster recovery design](https://trailassembly.com/salesforce-disaster-recovery/): Salesforce guarantees the platform stays up and your data survives their infrastructure failing. It does not protect you from your own mistakes, and the native tools give you a backup with no restore… - [An anti-patterns catalogue](https://trailassembly.com/salesforce-anti-patterns/): Most Salesforce orgs fail in the same handful of ways, and each is recognisable from a symptom you have probably already seen. Hardcoded IDs break on deployment. Multiple triggers on one object… - [Org consolidation: what it really costs](https://trailassembly.com/org-consolidation-cost/): Merging two Salesforce orgs costs far more than the licence saving, and the expensive part is not the data migration. It is reconciling two data models that encode two different definitions of the… - [Strategies for objects past ten million rows](https://trailassembly.com/objects-past-ten-million-rows/): Past ten million rows the useful moves are, in order, deleting data you do not need, bounding every query by date, getting custom indexes on the two or three fields your filters actually use, and… - [Lookup skew: many records pointing at one](https://trailassembly.com/lookup-skew/): Lookup skew is tens of thousands of records whose lookup field points at the same target record. When those records are inserted or updated in parallel, the platform takes a lock on the lookup… - [Reversibility as a design criterion](https://trailassembly.com/reversibility-as-a-design-criterion/): Before you make a structural decision in Salesforce, ask what it costs to undo. Most platform choices are cheap to reverse and a small number are effectively permanent, and the permanent ones are not… - [Master-detail vs lookup: the decision you cannot easily reverse](https://trailassembly.com/master-detail-vs-lookup/): Master-detail gives you roll-up summaries and cascade delete, and takes away the child's independent ownership and sharing. Lookup keeps the child independent and gives you neither. The reason this… - [One org or two: the reasons that hold and the ones that do not](https://trailassembly.com/single-org-vs-multi-org/): Stay in one org unless something forces you out, and the things that genuinely force you out are a short list: a regulator that requires separation, an acquisition you cannot merge inside a sensible… - [Pick the integration pattern before you pick the tool](https://trailassembly.com/choosing-an-integration-pattern/): Answer three questions before you open a middleware console. Who starts the conversation, does the starter need the answer right now, and how many records move per run. Those three answers pick the… - [Data skew: the 10,000-record line that decides how your org behaves under load](https://trailassembly.com/salesforce-data-skew/): Ownership skew, parent-child skew and lookup skew are one problem wearing three hats: a single row that everything else queues behind. Here is what each one breaks, and why taking one role off one… - [Why a query that was fast at 100,000 rows is slow at 5 million](https://trailassembly.com/selective-queries-at-scale/): Your filter stopped using its index. The query optimiser only uses an index when the filter matches fewer rows than a fixed threshold, and that threshold is a share of the table. A filter that… - [Salesforce order of execution, with Flow in it](https://trailassembly.com/order-of-execution/): Before-save record-triggered flows run before your before triggers, and after-save record-triggered flows run after workflow rules, not next to your after triggers. Everything else in the save order… - [Salesforce governor limits, organised by what actually trips them](https://trailassembly.com/governor-limits-reference/): Every limit below is counted per transaction, and a transaction includes every piece of code and configuration that runs during one save — your Apex, other people's Apex, every managed package… - [UNABLE_TO_LOCK_ROW: what is actually locked, and why it is never the record you think](https://trailassembly.com/unable-to-lock-row/): Two transactions want to write the same record, and yours waited too long. Salesforce locks a record while it is being written, a transaction will wait a maximum of ten seconds for that lock to… ## Agentforce and AI - [What is AIforce? It is not a product you can switch on](https://trailassembly.com/what-is-aiforce/): AIforce is the brand Salesforce put on its headless layer at Dreamforce '26. The capabilities under it are real, mostly older than the name, and documented as Headless 360. - [Human oversight in automated decisions](https://trailassembly.com/human-in-the-loop/): Decide which actions an agent may take alone and which need a person to approve, and enforce it in the action layer rather than in the instructions. - [Retrieval and vector search, practically](https://trailassembly.com/vector-search-retrieval/): Vector search finds passages that are semantically close to a question rather than ones sharing its keywords, which is why it answers "how do I stop being charged" with a document titled "Cancelling… - [AIforce, Claudeforce and MCP](https://trailassembly.com/aiforce-claudeforce-mcp/): AIforce turns your org into something an outside AI client can call, and Claudeforce is the first client to do it. The technology underneath is an MCP server plus your existing APIs. The important… - [Writing prompts that work against CRM data](https://trailassembly.com/prompt-engineering-for-salesforce/): Prompts against CRM data fail for three reasons, and none of them is that the prompt was not clever enough. The output format was left to the model, the empty and missing fields were not handled, and… - [Prompt Builder, from scratch](https://trailassembly.com/prompt-builder-basics/): Prompt Builder is a place to write a prompt, attach real record data to it with merge fields, see the resolved text before it goes anywhere, and activate it so other things can call it. The interface… - [The standard actions an agent can call](https://trailassembly.com/einstein-copilot-actions/): Standard actions are the pre-built things an agent can do without you writing anything, and they divide cleanly into ones that read, ones that write, and ones that generate text. The read actions are… - [The AI privacy questions your security team will ask](https://trailassembly.com/ai-data-privacy-questions/): Your security team will ask eight or nine questions, and the answers to most of them are good. The one that is not is "does our data leave the platform", where the answer is yes, it goes to a model… - [Agentforce versus chatbot](https://trailassembly.com/agentforce-versus-chatbot/): The real change is that you no longer write the dialogue tree. The agent decides what to do next from instructions and available actions rather than following branches you drew. That removes the… - [Agentforce service agent](https://trailassembly.com/agentforce-service-agent/): A service agent earns its place on the narrow band of contacts that are repetitive, answerable from published content, and low-consequence when wrong. It does that band well. Outside it, the agent… - [Agentforce sales agent](https://trailassembly.com/agentforce-sales-agent/): Sales agents are easier to ship than service agents because the audience is internal, the output is a draft rather than an answer, and a mistake costs a rep thirty seconds of editing instead of a… - [Agentforce rollout plan](https://trailassembly.com/agentforce-rollout-plan/): Pick one use case, one audience of about twenty people, and run it for four weeks with someone reading transcripts every day. That is the whole plan. Big-bang launches fail not because the agent is… - [Agentforce multilingual](https://trailassembly.com/agentforce-multilingual/): The model will answer in most languages whether or not you configured it to, which is the problem rather than the feature. Quality is uneven across languages, your grounding content is probably… - [Agentforce handoff to human](https://trailassembly.com/agentforce-handoff-to-human/): The handoff is not a feature you turn on at the end, it is routing infrastructure that has to exist before the agent does, and if your org has no working queue, availability model and skills setup… - [Agentforce guardrails](https://trailassembly.com/agentforce-guardrails/): A guardrail written as an instruction is a strong preference, not a constraint. It holds most of the time and fails quietly the rest. Anything that must never happen has to be enforced by what… - [Agentforce deployment](https://trailassembly.com/agentforce-deployment/): The agent definition, its topics and its actions are metadata and move through a normal deployment. Almost everything that makes the agent work in the source org is not, or is metadata that points at… - [Agentforce data grounding patterns](https://trailassembly.com/agentforce-data-grounding-patterns/): There are three ways to get real data in front of the model, and the question type decides which one. Record context for "what is the state of this thing", knowledge retrieval for "what is the… - [Agentforce conversation design](https://trailassembly.com/agentforce-conversation-design/): Conversation design is mostly three decisions. How much the agent asks before it acts, whether it confirms a consequential action before performing it, and what it does on the turn after it gets… - [Agentforce analytics](https://trailassembly.com/agentforce-analytics/): The three numbers everyone reports are deflection, escalation and containment, and all three can be improved by making the agent worse. Deflection rises when customers give up. Escalation falls when… - [Einstein Prediction Builder, honestly assessed](https://trailassembly.com/salesforce-einstein-prediction-builder/): Einstein Prediction Builder is a declarative way to train a model on records you already have and write a score onto a field. You point it at an object, tell it which field holds the outcome, let it… - [What Agentforce still cannot do](https://trailassembly.com/what-agentforce-cannot-do/): It cannot guarantee the same answer twice, it cannot do arithmetic you would bet money on, and it cannot run a long transaction reliably. Those are properties of the underlying technology rather than… - [Prompt template types, and when each applies](https://trailassembly.com/prompt-template-types/): The template type decides where the output can go, not how clever the prompt is. Sales email writes into an email composer, field generation writes into a field, record summary produces a summary of… - [PII in prompts: what leaves the org](https://trailassembly.com/pii-in-prompts/): The prompt leaves the org. That is the fact to start from. What leaves is whatever your template merged in and whatever an action returned, with recognised personal data replaced by placeholders on… - [Grounding a prompt with Data Cloud](https://trailassembly.com/grounding-a-prompt-with-data-cloud/): Merge fields put known data into a prompt. A retriever finds data you could not name in advance. If you know which record and which fields you need, merge fields are the right answer and Data Cloud… - [Your first Agentforce action, end to end](https://trailassembly.com/first-agentforce-action/): An agent action is an autolaunched Flow with a description written for a model to read. The Flow is the easy half. What decides whether the action ever gets used is the text around it: the action… - [Evaluating agent quality beyond vibes](https://trailassembly.com/evaluating-agent-quality/): Pick a fixed set of real requests, define what a correct outcome looks like for each, and count how many the agent completes. That number is the quality measure. Customer satisfaction scores, tone… - [The Einstein Trust Layer: what it does and does not do](https://trailassembly.com/einstein-trust-layer/): The Trust Layer sits between your org and the model provider. It masks certain sensitive data on the way out, holds a zero-retention agreement with the provider, scores responses for toxicity, and… - [Designing topics and instructions that hold](https://trailassembly.com/agentforce-topics-and-instructions/): A topic is a scope boundary. It decides which instructions and which actions exist for the current turn, and everything outside it is invisible while that topic is active. Instructions are… - [Testing agents in Testing Center](https://trailassembly.com/agentforce-testing-center/): Testing Center runs a batch of utterances through your agent and checks what it did, not how nicely it phrased the reply. The assertions that matter are which topic was selected and which action was… - [Custom actions: Flow-based or Apex-based](https://trailassembly.com/agentforce-custom-actions/): Flow-based actions are faster to build and easier for an admin to maintain. Apex-based actions give you control over what the agent receives, which matters most when things go wrong. The choice comes… - [What Agentforce actually costs to run](https://trailassembly.com/agentforce-cost-model/): Agentforce is metered on consumption rather than on seats, through Flex Credits. Actions that invoke a model consume credits, and a conversation consumes as many as its design requires. Which means… - [Agent, flow, or Apex: choosing](https://trailassembly.com/agent-flow-or-apex/): If the steps are known in advance, use Flow or Apex. An agent is for work where the path is decided by what a person says, and it pays for that flexibility with non-determinism, higher running cost… - [What an Agentforce agent is actually allowed to see](https://trailassembly.com/agentforce-permissions/): An agent needs three separate things, and people usually grant only the first. Permission to use the agent, permission for whatever identity runs its actions, and access to the data those actions… - [Prompt injection in a CRM: every text field a customer can write into](https://trailassembly.com/prompt-injection-in-a-crm/): Every text field a customer can influence is untrusted input, and an agent reading records is reading it as instructions unless something stops it. A case description saying "ignore previous… - [MCP explained for Salesforce architects](https://trailassembly.com/mcp-explained-for-salesforce/): A wire protocol that lets an AI client call tools on a server. Salesforce hosts the servers, each call runs as the authenticated user, and the blast radius is not the tool count — it is whatever… - [Getting your org ready for Claudeforce: four days of work you should do anyway](https://trailassembly.com/claudeforce-getting-your-org-ready/): Everything that decides whether Claudeforce is safe in your org is configurable today, before the pilot reaches you. An agent runs as the authenticated user through an External Client App with the… - [What you can actually do with Claudeforce, and who benefits](https://trailassembly.com/claudeforce-what-you-can-do-with-it/): Claudeforce puts your Salesforce data inside Claude, so the work happens where the person is already thinking instead of where the record lives. The first release is aimed squarely at sellers — 37… - [What an outside agent can see in your org, and who decides](https://trailassembly.com/external-agents-and-salesforce-access/): An agent acting for a user sees exactly what that user sees. Your sharing model is your AI policy, whether or not anybody wrote it down that way. What changes with an agent is not the permission —… - [Claudeforce: what Salesforce and Anthropic actually announced](https://trailassembly.com/claudeforce-what-was-announced/): Claudeforce is a partnership, not a product you install. The first thing shipping under it is Salesforce in Claude — a plugin that lets Claude read live Salesforce data and take actions, with 37… - [When an agent is the wrong tool](https://trailassembly.com/when-not-to-use-an-agent/): Do not use an agent where the outcome must be identical every time, where a regulator or an auditor will ask why a decision was made, or where the work is a fixed sequence with no interpretation in… ## LWC and Front-End - [The Lightning Message Service import needs a __c](https://trailassembly.com/lightning-message-service/): Lightning Message Service is how two components that share no DOM ancestry talk to each other, and the thing that breaks the first deploy is almost always the import. Your channel file is named… - [refreshApex and stale data after a save](https://trailassembly.com/refreshapex-stale-data/): RefreshApex re-runs a wired Apex method and updates everything bound to it, and it only works if you kept the whole wire result — not just result.data. Store the provisioned value, pass that same… - [Lightning Data Service: what it caches and when it lies](https://trailassembly.com/lightning-data-service-cache/): Lightning Data Service keeps a client-side record cache shared by every component on the page, which is why getRecord is fast and why your component sometimes shows a value that is no longer true… - [Showing errors properly in LWC](https://trailassembly.com/lwc-toast-and-error-display/): A toast is for confirming something that worked and for reporting a failure the user cannot act on. An error tied to a specific field or a specific form belongs next to that field, on screen, where… - [Loading a third-party library in LWC](https://trailassembly.com/lwc-third-party-libraries/): Upload the library as a static resource, import it with @salesforce/resourceUrl, and load it with loadScript from lightning/platformResourceLoader before you touch its API. Loading a script straight… - [lwc:if, for:each, and the key requirement](https://trailassembly.com/lwc-template-directives/): Use lwc:if, lwc:elseif and lwc:else for conditionals, for:each for ordinary lists, and iterator only when you need to know which item is first or last. Every list item needs a key, that key must be a… - [Slots and composition in LWC](https://trailassembly.com/lwc-slots-and-composition/): A slot is a hole in a child's template that the parent fills with its own markup, and reaching for one is the right move when the variations between usages are structural rather than a handful of… - [Getting record context in an LWC](https://trailassembly.com/lwc-record-context/): Declare @api recordId and @api objectApiName and the platform fills them in, but only when the component is hosted somewhere that has a record. A record page and a record quick action both provide… - [LWC as a quick action](https://trailassembly.com/lwc-quick-actions/): An LWC can be a quick action in two shapes. A screen action opens your component in a modal and you close it yourself with CloseActionScreenEvent. A headless action renders nothing and runs an @api… - [LWC performance, measured before optimised](https://trailassembly.com/lwc-performance/): Almost every slow Lightning page is slow for one of three reasons. Too many server round trips on load, too many DOM nodes rendered at once, or expensive work running on every render. Measure first… - [NavigationMixin and page references](https://trailassembly.com/lwc-navigation-service/): Apply NavigationMixin to your class, build a page reference object that describes where you want to go, and pass it to this[NavigationMixin.Navigate](). Never build a URL by concatenating the org… - [Modals with the LightningModal base class](https://trailassembly.com/lwc-modals-and-lightning-modal/): Extend LightningModal rather than building a dialog out of SLDS markup by hand. The base class handles the overlay, the focus trap, the escape key, the ARIA roles and the stacking, and it gives you a… - [lightning-datatable, and when to stop using it](https://trailassembly.com/lwc-lightning-datatable/): Lightning-datatable gives you a styled, accessible, virtually scrolling grid for the price of a columns array and a key-field. It does not sort your data, it does not save your edits, and it does not… - [The LWC lifecycle hooks, and the renderedCallback trap](https://trailassembly.com/lwc-lifecycle-hooks/): There are five hooks worth knowing. constructor sets field defaults and nothing else, connectedCallback is where subscriptions and initial data fetches belong, renderedCallback is the only place you… - [Getters against tracked properties](https://trailassembly.com/lwc-getters-and-reactivity/): Every field on a modern LWC class is already reactive, so @track is only needed when you mutate the inside of an object or array rather than reassigning it. Derived values belong in getters, not in… - [Building an LWC for a flow screen](https://trailassembly.com/lwc-flow-screen-components/): Add the lightning__FlowScreen target to the meta file, declare each flow-visible property in a targetConfig, read inputs through @api properties, and push values back with FlowAttributeChangeEvent… - [Styling LWC: shadow DOM, SLDS and styling hooks](https://trailassembly.com/lwc-css-and-styling/): Every LWC has its own stylesheet and the shadow boundary keeps it there. Your CSS cannot reach inside a child component and the page's CSS cannot reach inside yours. That is not a limitation to work… - [Error handling in imperative Apex calls](https://trailassembly.com/lwc-apex-imperative-error-handling/): An uncaught Apex exception reaches the browser as a generic internal server error with none of your message in it. To send the user something useful you must throw an AuraHandledException carrying a… - [Accessible Lightning Web Components](https://trailassembly.com/lwc-accessibility/): Use base components and give them real labels, manage focus whenever the DOM changes under the user, and test with the keyboard before you test with anything else. The base component library has done… - [Lightning record page performance](https://trailassembly.com/lightning-page-performance/): A slow record page is usually slow because of how many things it asks the server for, not because of how much is on screen. Every component with its own Apex controller is a round trip, every related… - [Building LWCs for Experience Cloud](https://trailassembly.com/lwc-in-experience-cloud/): The component is the same, the meta file is not. You add lightningCommunity__Page and lightningCommunity__Default as targets, you declare every configurable property in a targetConfig, and you pass… - [LDS wire adapters, and when to stop writing Apex](https://trailassembly.com/lwc-wire-adapters-lds/): If a Lightning Data Service wire adapter can answer your question, use it instead of writing an Apex controller. getRecord, getRelatedListRecords, getObjectInfo and getPicklistValues share one cache… - [lightning-record-form, record-edit-form, or building it yourself](https://trailassembly.com/lwc-record-form-vs-custom/): Use lightning-record-form until it stops fitting, drop to lightning-record-edit-form when you need to control which fields appear and what sits between them, and write a fully custom form only when… - [Cannot read properties of undefined, in a wire handler](https://trailassembly.com/lwc-cannot-read-properties-undefined/): Your wire adapter emits before the data arrives, so the property you are reading is undefined at the moment the getter or the template runs. The error is not telling you the record is missing. It is… - [Lightning Web Security: what changed when it replaced Locker](https://trailassembly.com/lightning-web-security-migration/): Lightning Web Security replaced Locker Service and is more permissive, not less. Most components that worked under Locker work under LWS unmodified. The ones that break share a pattern: they relied… - [Aura to LWC: a migration order that does not strand you](https://trailassembly.com/aura-to-lwc-migration-order/): Migrate leaves first and work upwards, because an LWC can contain an Aura component only by not containing it. Aura can hold an LWC child. An LWC cannot hold an Aura child. Get that one rule wrong… - [How Lightning Web Components talk to each other](https://trailassembly.com/lwc-component-communication/): Down the tree use public properties, up the tree use a CustomEvent, and sideways use the Lightning Message Service. Three mechanisms, and the mistake that causes most of the confusion is reaching for… - [The LWC Jest tests worth writing](https://trailassembly.com/lwc-jest-tests-worth-writing/): Test what the component does, not what it renders: the events it fires, the Apex it calls with which arguments, and how it behaves when a wire returns an error. Markup assertions fail on every… - [Your LWC property changed and nothing re-rendered](https://trailassembly.com/lwc-reactivity-not-updating/): You mutated something instead of replacing it. LWC re-renders when a field's value is reassigned, and reassignment is not the same as changing what is inside an object or an array. this.rows.push(x)… - [Your LWC shows old data after a save: which cache is lying](https://trailassembly.com/lwc-stale-data-after-save/): Your component is showing a cached value, and which cache decides the fix. Wired Apex is refreshed with refreshApex. Lightning Data Service is refreshed with notifyRecordUpdateAvailable. Using the… - [@wire or imperative: how an LWC should call Apex](https://trailassembly.com/lwc-wire-vs-imperative-apex/): Use @wire when the component displays data and the framework should manage it, and an imperative call when the user's action decides when the call happens. The rule that decides most cases is not… ## DevOps and Release - [Scratch orgs vs sandboxes: what each one is a copy of](https://trailassembly.com/scratch-orgs-vs-sandboxes/): A scratch org is built from your repository and expires within 30 days, while a sandbox is a copy of production that you refresh on a schedule. - [SLIs and SLOs for a Salesforce org](https://trailassembly.com/slis-and-slos/): Pick three or four things users actually notice, measure them, and set a target you are willing to be held to. On Salesforce the useful indicators are save latency on your busiest object, scheduled… - [The operational readiness review before go-live](https://trailassembly.com/go-live-readiness-review/): An operational readiness review asks who will run this thing on the Tuesday after launch, not whether the code works. Run it two weeks before go-live, with the people who will carry the pager in the… - [DevOps Center vs the CLI](https://trailassembly.com/devops-center-vs-cli/): DevOps Center gives you version control with a point-and-click interface, which is the right answer for an admin-heavy team that would otherwise still be on change sets. The CLI gives you everything… - [Change Sets: when they are still the right tool](https://trailassembly.com/change-sets-vs-sfdx/): Use the CLI and version control. Change sets are still defensible in exactly one situation — a small org with no developers, no repository, and no appetite to build one — and even then the… - [Validation-only deploys and quick deploy](https://trailassembly.com/validation-only-and-quick-deploy/): Run a validation-only deployment against production ahead of your window, and if it passes with tests, you get a quick deploy that skips the test run entirely — turning a two-hour release into a… - [Source tracking, push and pull](https://trailassembly.com/sfdx-source-tracking/): Source tracking makes the org remember which metadata changed since you last synced, so sf project retrieve start and sf project deploy start can move only the delta. It works in scratch orgs and in… - [Changing schema in a live org](https://trailassembly.com/salesforce-schema-changes-checklist/): A schema change in a live org is safe when you have found everything that references the thing you are changing, and unsafe when you have not. Setup's own dependency tools find most of it and miss… - [The sandbox refresh checklist](https://trailassembly.com/salesforce-sandbox-refresh-checklist/): A freshly refreshed sandbox is a copy of production that still believes it is production, and the first job is to stop it behaving like one. Email deliverability, integration endpoints and scheduled… - [Writing a postmortem people actually read](https://trailassembly.com/salesforce-postmortem/): A postmortem people read is short, has a timeline with real timestamps, avoids naming anyone as a cause, and ends with three or four actions that have owners and dates. Most postmortems fail on the… - [Incident response for a Salesforce org](https://trailassembly.com/salesforce-incident-response/): Establish blast radius, stop the bleeding, tell people, then fix it, in that order. The instinct to go straight to the fix is what turns a thirty-minute incident into a four-hour one, because you… - [Pair programming](https://trailassembly.com/salesforce-pair-programming/): Pairing works well on Apex and LWC, works badly on point-and-click configuration, and is worth using deliberately rather than as a default. The reason declarative work resists it is mechanical: one… - [Onboarding a developer](https://trailassembly.com/salesforce-onboarding-a-developer/): Give them access on day one, a real ticket by day three, and the org's history before you give them its architecture. Most onboarding fails because it front-loads documentation nobody can absorb and… - [Code review](https://trailassembly.com/salesforce-code-review/): Review for correctness under volume, for security, and for whether the thing matches what was asked. Leave style to a linter and leave personal preference alone entirely. A Salesforce review that is… - [Second-generation packaging from scratch](https://trailassembly.com/second-generation-packaging/): A second-generation package is defined by your repository, not by an org. You describe the package in sfdx-project.json, build a version from source with the CLI, install it somewhere to test, then… - [Namespaces: the decision you cannot reverse](https://trailassembly.com/salesforce-namespaces/): A namespace is registered once, globally unique, and permanent. It cannot be renamed, transferred to another prefix, or released back if you stop using it. Pick something short and boring that… - [Package upgrade behaviour](https://trailassembly.com/package-upgrade-behaviour/): Installing a newer version over an older one upgrades in place and keeps every record. Subscriber customisations to components they are allowed to edit survive. Uninstalling is the destructive one… - [The AppExchange security review](https://trailassembly.com/isv-security-review/): The security review checks your package for the same handful of vulnerabilities every time, and most first submissions fail on one of them. Run the Salesforce Code Analyzer yourself, fix everything… - [Deprecating Apex in a managed package](https://trailassembly.com/deprecating-apex-in-a-package/): @deprecated stops new subscriber code referencing a global member. It does not remove anything. Once a global class, method, interface or enum ships in a released managed package, it exists in every… - [1GP against 2GP: what freezes at upload](https://trailassembly.com/1gp-vs-2gp/): First-generation packages are defined by a packaging org, second-generation packages are defined by your source. That single difference produces every other difference worth caring about. Start new… - [Release management: internal teams against ISVs](https://trailassembly.com/salesforce-release-management-isv/): An internal team ships to one org they control and can fix forward. An ISV ships to hundreds of orgs on versions they do not control and cannot fix forward. Everything else about how the two work… - [Triaging a deployment failure](https://trailassembly.com/sf-cli-deployment-failures/): Read the component failure list before you read anything else, and work out whether you are looking at a component error or a test error, because they have nothing to do with each other. A component… - [Test levels for deployment](https://trailassembly.com/salesforce-test-levels/): Use RunLocalTests for production and for any validation you intend to quick-deploy, NoTestRun for sandboxes where you are iterating, and RunSpecifiedTests only when you understand that it changes the… - [A branching strategy for Salesforce teams](https://trailassembly.com/salesforce-branching-strategy/): One short-lived branch per work item, cut from the branch that represents your highest sandbox, merged back through a pull request, deleted the same week. Git flow, with its permanent develop, its… - [CI/CD for Salesforce with GitHub Actions](https://trailassembly.com/github-actions-salesforce-cicd/): Two workflows. One runs on every pull request and does a validation-only deployment with tests. One runs on merge to your production branch and deploys. The only fiddly part is authentication. The… - [Deploying flows without breaking the active version](https://trailassembly.com/deploying-flows-without-breaking/): A flow deployment never overwrites the running version. It adds a new version, and whether that version becomes the active one depends on the status element in your file and on an org setting in… - [The Salesforce CLI commands you actually use](https://trailassembly.com/salesforce-cli-commands/): There are about twelve commands you will use daily and several hundred you will not. This is the working set, in the sf syntax that replaced sfdx, with the flags that matter and the two or three… - [Change sets, source-tracked deployment, or packages](https://trailassembly.com/salesforce-deployment-options/): Change sets are fine for a small org with occasional changes, source-tracked deployment from a repository is right for everyone else, and unlocked packages are worth it only when you have something… - [A sandbox strategy you can actually keep to](https://trailassembly.com/salesforce-sandbox-strategy/): One preview-track sandbox for releases, one integration sandbox with production-shaped data, and developer sandboxes created per piece of work. The failure is never too few sandboxes — it is three… ## Reports and Analytics - [A report takes two row-level formulas, not three](https://trailassembly.com/report-row-level-formulas/): A Salesforce report accepts two row-level formulas. Ask for a third and the metadata deploy rejects the whole report. Inside the formula you reference the report's column name rather than the field's… - [SAQL basics for SQL people](https://trailassembly.com/saql-for-sql-people/): SAQL is not SQL with different keywords. It is a pipeline language — you load a dataset, then pass it through a sequence of transformation steps, each one taking a stream and producing a stream… - [Why two users see different numbers](https://trailassembly.com/report-different-results-different-users/): The same report shows different numbers to different people because reports respect record access, and access differs by user. Before you suspect the report, confirm it: have both users open the… - [Reporting on service performance](https://trailassembly.com/service-cloud-reporting/): Salesforce gives you case volume and case age for free, and nothing else that matters. First response time, resolution time against business hours, and reopened case counts all have to be built… - [Reporting on pipeline over time](https://trailassembly.com/sales-cloud-reporting/): A Salesforce report shows the current state of records. It cannot tell you what your pipeline looked like six weeks ago, because that information does not exist unless something was capturing it at… - [Collaborative Forecasting, and why the number differs](https://trailassembly.com/salesforce-forecasting/): Collaborative Forecasting rolls opportunity amounts up the role hierarchy, grouped by forecast category, and lets each manager adjust their number without changing any opportunity. That last part is… - [Reporting snapshots for trend analysis](https://trailassembly.com/reporting-snapshots/): A reporting snapshot runs a report on a schedule and writes its results into a custom object, so you can report on history that Salesforce does not otherwise keep. It is the only native way to answer… - [Reporting on field history](https://trailassembly.com/reporting-on-history-objects/): Field history tracking records old and new values for up to twenty fields per object, and those rows are reportable through standard "with history" report types. The data is kept for a limited… - [Summary formulas: PARENTGROUPVAL and PREVGROUPVAL](https://trailassembly.com/report-summary-formulas/): A custom summary formula is calculated after the report has grouped its rows, it can only reference summarised values, and the "display at" setting decides whether you get a number or a blank cell… - [Report subscriptions, and why the email is empty](https://trailassembly.com/report-subscriptions-and-schedules/): A report subscription runs a report on a schedule and emails the result, and the critical setting is who it runs as. Run it as yourself and recipients see your data, not theirs. That is the same… - [Report and dashboard folder sharing](https://trailassembly.com/report-folders-and-sharing/): Report and dashboard access is controlled by folders, not by records. A folder is shared with users, roles or groups at one of three access levels, and that decides who can open, edit or manage what… - [Filter logic, cross filters and the filters that cannot be indexed](https://trailassembly.com/report-filter-logic/): Filters in a report are combined with AND until you write filter logic, and filter logic is an expression over the numbers Salesforce assigns to your field filters. Cross filters are not in that… - [Bucket fields, and where they break](https://trailassembly.com/report-bucket-fields/): A bucket field groups values into categories inside one report, without a formula field, without a deployment, and without anyone else being able to use it. That last part is the catch. A bucket is a… - [Matrix reports, and when one beats a summary](https://trailassembly.com/matrix-reports/): A matrix report groups by rows and by columns at the same time, so each cell is a summary of the records sitting at that intersection. Use it when the question has two dimensions and one measure. Use… - [Joined reports, and when they are the wrong answer](https://trailassembly.com/joined-reports/): A joined report puts up to five independent report blocks side by side, aligned on fields they have in common. It is the only way to show Opportunities and Cases in one result without a custom report… - [Exporting reports, and why the export differs](https://trailassembly.com/exporting-report-data/): Salesforce offers two exports and they produce different files. Formatted Report keeps the groupings, subtotals, summary formulas and headers, and is capped at 100,000 rows. Details Only gives you… - [Dynamic dashboards, and the per-edition cap](https://trailassembly.com/dynamic-dashboards/): A dynamic dashboard runs as whoever is looking at it, so every viewer sees their own data from one dashboard instead of you building one per team. Salesforce caps how many you can have per org, and… - [Dashboard filters and component choice](https://trailassembly.com/dashboard-filters-and-components/): A Lightning dashboard allows three filters, each applied across every component whose source report has an equivalent field. Three is the hard ceiling and it shapes the design more than anything… - [Cross filters: records with or without related records](https://trailassembly.com/cross-filters-and-with-without/): A cross filter keeps or removes parent records based on whether related child records exist. "Accounts without Opportunities" is the canonical example and it is the one you cannot build any other way… - [CRM Analytics or standard reports](https://trailassembly.com/crm-analytics-vs-reports/): Standard reports are live, sharing-aware, free with your licence, and limited to four joined objects. CRM Analytics works on extracted datasets, blends data from outside Salesforce, handles far… - [Report types, and why yours is missing fields](https://trailassembly.com/salesforce-report-types/): The report type decides which objects and fields a report can ever see, and you cannot change it after the report is created. A field missing from a report is nearly always a report type problem, not… - [Dashboard running user, and the numbers that change per viewer](https://trailassembly.com/dashboard-running-user/): A dashboard shows data as one specific user, and by default that is not the person looking at it. Two people opening the same dashboard see identical numbers, which are the numbers the running user… - [Why your Salesforce report is slow](https://trailassembly.com/salesforce-report-performance/): Reports use the same optimiser, indexes and selectivity thresholds as SOQL — you just cannot see the query plan. So you diagnose by elimination: strip the filters, then add them back one at a time… ## Career and Certification - [Contributing to open source in the ecosystem](https://trailassembly.com/open-source-in-the-ecosystem/): Contributing to Salesforce open source is the fastest way to have your work seen by people who can hire you, and the lowest-risk way to learn how experienced developers structure code. Start by… - [Reading a Salesforce job description honestly](https://trailassembly.com/reading-a-job-description/): Most Salesforce job descriptions are wish lists assembled from other job descriptions, so read them for the two or three requirements that repeat in different words — those are the real job. Apply… - [How people actually become Salesforce MVPs](https://trailassembly.com/becoming-an-mvp/): Salesforce MVP is awarded, not applied for in the usual sense — you are nominated, and the selection weighs sustained community contribution, expertise and the way you treat people. - [Trailhead versus actually building things](https://trailassembly.com/trailhead-vs-building/): Trailhead teaches you what the features are; building something teaches you what happens when they interact. You need both, in that order, and the transition point comes earlier than most people take… - [Going independent: the parts nobody mentions](https://trailassembly.com/going-independent/): Going independent as a Salesforce consultant is a sales job with some Salesforce work attached. The technical part is the part you already know how to do. What determines whether it works is… - [CTA: an honest assessment of the cost](https://trailassembly.com/cta-honest-cost/): The Certified Technical Architect is the most expensive credential in the ecosystem in time and money, and the review board is a five-hour presentation and defence of a solution you design under… - [Salary and negotiation](https://trailassembly.com/salesforce-salary-and-negotiation/): Pay on this platform tracks scarcity and responsibility, not credentials or years. The two reliable ways to move it are changing employer and acquiring a skill that is hard to hire for, and the first… - [Mvp and community](https://trailassembly.com/salesforce-mvp-and-community/): Nobody becomes a Salesforce MVP by trying to become one, and the people who visibly want it rarely get it. The award recognises a pattern of helping other people that has already been going on for a… - [Interview questions](https://trailassembly.com/salesforce-interview-questions/): A good Salesforce interview asks you to make a decision and then defend it. A bad one asks you to recite a limit. The difference matters to you as a candidate because it tells you what the team is… - [Freelancing](https://trailassembly.com/salesforce-freelancing/): The Salesforce work is the easy part. Freelancing fails on the three things that have nothing to do with the platform: finding the next client before the current one ends, writing down what you… - [Consultant vs inhouse](https://trailassembly.com/salesforce-consultant-vs-inhouse/): Consultancy teaches you breadth fast and costs you the ending, because you rarely see what your work did after the go-live party. In-house teaches you consequence, because you live with every… - [Certification strategy](https://trailassembly.com/salesforce-certification-strategy/): Take Administrator, take the one developer or consultant credential that matches the work you are actually paid to do, then stop until a real gap or a real job requirement appears. The returns fall… - [Architect path](https://trailassembly.com/salesforce-architect-path/): The architect job is mostly refusing things and writing down why. The certifications, up to and including the CTA review board, prove you know the platform's capabilities and can defend a design… - [Admin to developer](https://trailassembly.com/salesforce-admin-to-developer/): More transfers than people expect, but none of it is the part that makes the job hard. Your data model knowledge, your grip on the order of execution, your instinct for what the business actually… - [Getting your first Salesforce job](https://trailassembly.com/salesforce-first-job/): Certifications get you filtered in, and a thing you built gets you hired. Most people do these in the wrong order, spending months on a second certification when an afternoon building something real… - [Building a portfolio with no client work](https://trailassembly.com/building-a-salesforce-portfolio/): One project built properly and written up honestly beats five half-finished ones. The write-up is what does the work, because anyone can produce screenshots of an org and almost nobody explains the… - [Keeping up with three releases a year](https://trailassembly.com/staying-current-with-releases/): About three hours per release, three times a year, spent in a fixed order, and you will be better informed than most people on your team. The release notes are enormous because they document every… ## Release Coverage - [Reading release notes efficiently](https://trailassembly.com/reading-release-notes/): Do not read the release notes front to back. Read the Release Updates page in your own org first, because that is the list of changes that will break something on a date. Then filter the notes to the… - [Getting onto a sandbox preview instance](https://trailassembly.com/sandbox-preview-instance/): Whether a sandbox gets the next release early is decided by which instance it sits on, and that is fixed when the sandbox is created or refreshed — not by a setting you can toggle later. - [Dreamforce '26: what actually shipped](https://trailassembly.com/dreamforce-26-what-actually-shipped/): Dreamforce '26 closed today, and almost nothing announced on the main stage is something you can turn on this afternoon. Seven agents are GA. The headline product, AIforce, ships through a Claude… - [Benioff's Dreamforce '26 keynote: the five claims](https://trailassembly.com/benioff-df26-keynote-notes/): Marc Benioff's Dreamforce '26 keynote made one argument, repeated five ways — that Salesforce's value was never the screen you log into, and that the company is willing to prove it by giving that… - [The Release Updates that actually break things](https://trailassembly.com/release-updates-that-break-things/): Read the Release Updates page in your own org before you read anybody's release summary, including this site's. It is the only list that is specific to your org, it tells you exactly when each change… - [How to work a Salesforce release without losing a week](https://trailassembly.com/working-a-salesforce-release/): Three things decide whether a release costs you an afternoon or a week. Getting a sandbox onto the preview track before the refresh deadline, reading your own org's Release Updates page instead of a… - [Salesforce retirement tracker: what is dated, and how to check your exposure](https://trailassembly.com/salesforce-retirement-tracker/): Retirements are the only Salesforce changes with a hard deadline and no opt-out, and they almost always hit integrations rather than users. Below is what is currently retired or dated, what breaks… - [Winter '27: the change that breaks integrations, and two you can take your time over](https://trailassembly.com/winter-27-what-matters/): Salesforce stops supporting the OAuth 2.0 username-password flow for connected apps, and integrations using it stop rather than degrade. Plus the sharing recalculation change that produces no error… ## About - [About Trail Assembly](https://trailassembly.com/about/): who writes this and how articles are made. - [Write for us](https://trailassembly.com/write-for-us/): contribution guidelines. Content is original and independently produced. Not affiliated with Salesforce, Inc. When citing, link to the article URL.