Create a Roll-Up Summary with Flow

Here is a (relatively) simple example of how you can create a roll-up summary with Flow. It counts how many contacts exist for a given account and keeps this number up to date as you add/edit/delete contacts that are related to this account.

You can easily take this principle and apply it to any two related objects.

Create a new Account field

Starting with the Account object (where we want our counter) we create a new number field (with 0 decimal places) called Count of Contacts (Count_of_Contacts__c).

Add the Count of Contacts to your Account Page Layout.

If you don’t add this field to your page layout, you will not see the result!

Now we are ready to create our first flow:

To start building this flow, create a new flow, type = Record Triggered Flow.

The object is the contact as you want to see when a change occurs on a contact record – eg it gets related to an account. You need to do this after the contact record is saved.

Unfortunately, there are no filters on the contact that we can use to determine if we need to update the account contact count so we have to check them all. It’s not a very efficient method but it only runs when we create or update a contact record. The ideal situation would be to only update those where the record is new or the AccountId has been added or changed. Using the ISCHANGED operator sounds like the solution, however, it will always be true when we create a new contact as the AccountId will go from null to a valid AccountId.

Add a Decision element:

Now add a decision to see if the AccountId has been changed. The YES condition is for an existing contact record where the related Account (Account ID) has been changed.

Add a Get Records element (for Prior accounts):

Now we are heading down the Yes side of the branch:

Here we\\you want to get any contact records where the Account Id was changed on the contact. You need to update this account because the contact record may no longer be related to the account and the count needs to be recalculated.

We want to count any contact records where the Account Id is the same as the contact record that triggered this flow – prior to the change (they were related to the same account). To do this, we use the $Record_Prior.

We get all the related records but only store the Id (of the contact) and the Account Id fields. We store these into a variable rc_ContactsPrior which is a record collection of contacts, potentially containing many contact records.

First, we need to create a variable to save these records to:

(see below to create rc_Contacts).

rc_Contacts Variable

Create this new variable:

Back to the get records element:

ContactsCounterPrior variable

Create another variable to store how many contacts were found:

Create an Assignment Element

Set our new counter to the number of contact records we found for the Prior record..

Add an Update Records Element:

Next, update the Prior Account record with the new count of contacts:

Now do the remainder (for all records) so you cover records where a new contact has been added, this will update the count for them.

Get our contacts, this time we are using $Record for the current Account record.

Add a new record collection variable to count them:

Add the fields we want in our record collection:

Create another new variable for the count of records:

Assign the value to the counter: (add Assignment)

Update our Account with the new counter value:

Save your Flow

Finally check your flow looks like the one in this pic:

and Save your flow giving it a meaningful name eg:


Enable your flow.

Now you have a counter for when a contact is updated and linked to your account. But what happens if the contact is deleted? You need another flow!

It is simpler than the previous one.

Create another Record Triggered Flow.

This one will take care of any contact records that are deleted.

Again, create a new Record Triggered Flow.

This time the trigger is when a record is deleted and we can run it before the record is deleted.

Create the rc_Contacts collection variable

Get all contacts where the Account ID is the same as the record being deleted

Create the counter variable

Add the Assignment to both count the number of matching contacts AND to subtract 1 for the record being deleted.

Update the Account with the new count of contacts.

Save the Flow eg as: Accounts-CountContacts-DeleteTrigger

Activate the Flow.

Add the Count of Contacts to your Account Page Layout.

Now, you can test it out. Find an account that already has a related contact and add another one.

Change the Account for an existing contact and check that both the old account and new account now have the correct counters. Note: You may need to refresh the account page to get the new values.

Want more great flow learning like this?

Go to our new Learning Salesforce Flow course at and get started on your flow journey.

Similar Posts


  1. Hello,
    I have created a similart flow.
    it works great in the debug – but it doesn’t update the field when I do the process through the UI.

    Please help 🙏

  2. Hi there, thank you for putting this together. I am trying to implement a similar flow and when I go to set up the decision element and add in the resource (record > account id) I am getting the following error “The “Account” field doesn’t exist on the “Contact” object, or you don’t have access to the field.” Any idea why I might be getting this error? The Account field most definitely exists on the Contact object. I obviously can’t make much progress on this flow without successfully creating this decision element, so any help you can provide would be greatly appreciated.


    1. Hi Rachel, When you are selecting the account field, it can exist in two places. One as a field called account (on the contact) and then under the related objects (indicated with a > following the name) and then you get to access all the account fields and select Id from there (account.Id). Try both and see which one of them works for you.

  3. Hello Daryl,
    Thank you for this great content. My flow to count the # of active Assets on an Account is working for the counting part, but I am stuck with an error on my Update Records element: “The flow tried to update these records: 0013w00002b9sjRAAQ. This error occurred: INVALID_CROSS_REFERENCE_KEY: invalid cross reference id.” The record ID it’s referencing is the correct account for the Asset I chose during debug.

    My Update Records element is on the Account object and the only condition requirement is:
    Id equals {!$Record.AccountId}
    I’ve also tried using these values but get the same results:
    Id equals $Record > Account ID > Account ID
    Id equal $Record > Account ID

    I’ve searched the Invalid Cross Reference ID error but it mostly suggests access issues, which aren’t the case here. (I’m Sys Admin and have full access to the account field the flow is trying to update).

    I’d appreciate any help you can provide. Thank you!

    1. Hi Joy, The invalid cross reference ID usually refers to using the wrong ID on an update records. That ID starting with “001” prefix is an account ID, not an asset record.
      Copy that ID 0013w00002b9sjRAAQ into your browser and paste after the .com part of your URL.
      eg: (replace test with your domain name). This should display an account record, not an asset record.
      The prefix for an asset record is: “02i” – eg 02i0T0000007mxYQAQ so it looks like you are trying to update the wrong record.
      There is a good index to all prefixes here: (search for asset)

      1. Hi Daryl,
        Thank you for the response! Yes, I agree that 0013w00002b9sjRAAQ is an account record, but that is the object I’m trying to update. Similar to your “Edit Update Records” screenshot above, I’m attempting to update an Account field, “Count_of_Active_Assets__c,” with the variable “ActiveAssetCount.” The Get Records and Assignment elements are working properly during debug as I’m getting the correct Asset count, but then the invalid cross ref ID when trying to update the Account field with the results. And the record ID that the flow fails to update is the correct Account (related to the Asset I edited during debug). I’m stumped. Thank you again!

          1. Wanted to close the loop for anyone who might stumble on this “invalid cross reference id” error in the future. Finally determined the error is due to our full copy sandbox not being a true full copy: our prod org is over its data storage limits so when dev refreshed full, they couldn’t bring over ALL the data; they had to migrate some of it, leading to the missing reference IDs. If you’re getting this error in the future and have ruled out any access issues or flow issues, try it in a different environment where you know the data set is complete (or you manually create the records for testing).

            Thank you again, Daryl, for being so generous with your time and expertise to troubleshoot my flow and review my screenshots. Much appreciated!

  4. Hi Daryl,
    The Update and Delete record works fine for me. Delete flow is deleting one by one record. but If i delete more than one record using data loader.It not showing exact records. only one record is deleting at a time.
    Can you give me any idea how to delete multiple records and update that proper records.

    1. Hi Prachi, when you use data loader to do a bulk delete of records it is doing this via the API and not triggering the delete flow so as a result the number of records is not being updated. What you could do is run a scheduled flow (frequency will depend on how often you use the data loader to delete records) to recalculate the number of related records. This is potentially dangerous as there could be a large number of records to update as you have no entry criteria on the flow to identify which records need to be recalculated. If you deleted a contact attached to an account for example, the account record itself will not be updated so you can’t filter based on last updated date of the account. The other options are to use a tool like Declarative Lookup Rollup Summary (DLRS) or if there is a master-detail relationship between your two objects, simply use a rollup summary field.

      Between Account and contact there is only a lookup relationship so if you need to count contacts on accounts then DLRS is your best bet.

      DLRS Details here:

      It’s a bit tricky to setup the first time but once you get the hang of it, it is a very powerful tool.

  5. Thank you for this. It works great when a new contact is added or deleted, but how do I get it to run on all my existing accounts to fill in the contact counter?

    1. Great question Meagan.

      As this flow is triggered on the update of contact then we need to force an update of all contacts where the counter has not been updated. This is the way I would approach it:

      1. Create a checkbox field on contact eg “need_to_update” and set to false as default. 2. Export all contact records with dataloader. Make sure you include last updated date and the new need_to_update field plus the contact ID. Those are the only fields you will need. 3. Edit the extract file and remove all those contacts that have already been updated by the new flow (since you installed it) by sorting by the last updated field. 4. Update all the remaining records so the need_to_update is set to true. 5. Break the remaining file into “reasonable” sized parts – create a number of files each with a few hundred/thousand records*. 6. Change your dataloader batch size (in settings) to say 25-50 records. 7. Upload the new files (update records) and only map the contactID and need_to_update fields. 8. Repeat for each of the new upload files.

      * the number of records in each update file is a bit arbitrary, basically we need to slow down the number of records that are being updated at once and can do that with a combination of small upload file sizes and reducing the batch size. If you are getting errors on the updates, then you can reduce the file size and/or the batch size even further until you find a happy balance.

  6. Hi ,

    I tried this flow count is working base on the count wrote validation rule if count>1 for consumer account. I am getting below error when edit contact. “We can’t save this record because the “Number of related contact on Account” process failed. Give your Salesforce admin these details. This error occurred when the flow tried to update records: DUPLICATE_VALUE: duplicate value found: Number_of_Contacts__c duplicates value on record with id: 0013t000.”

Leave a Reply