Platform App Builder study materials
Platform App Builder study resources

Rollups, Ownership, and 220,000 Disbursements

Platform App Builder · Put your knowledge to work in context.

All case studies

Rollups, Ownership, and 220,000 Disbursements

Northgate Grants tracks Grant__c records with related Disbursement__c records through a lookup today. Finance wants two values on the grant - total disbursed amount and a count of disbursements - that appear in list views, reports and dashboards, not just on the page. A nightly integration upserts roughly 4,000 disbursements through Data Loader, and each row carries a legacy payment ID that must stay unique. Grants are owned by program managers across 9 business units; finance clerks create disbursements but should only see grants in their own unit. When a grant is deleted today its disbursements survive as orphans and skew reporting. Volume is 12,000 grants and 220,000 disbursements, and managers who own more than 800 grants report slow list views.

1. Which relationship type should Grant__c and Disbursement__c have, and what do you give up by choosing it?

Read the worked answer

Make Disbursement__c the detail side of a master-detail relationship.

Why:

  • Stored rollups. SUM and COUNT rollup summary fields are native to master-detail. The requirement is that the totals show up in list views, reports and dashboards - that means a stored field on the grant, not a formula on the child, a Lightning component, or a flow that recalculates on page load.
  • Orphan problem disappears. A detail record cannot exist without its master, and deleting a grant cascades to its disbursements. Today's orphans are a direct symptom of the lookup.
  • Ownership/sharing aligns with the requirement. On master-detail the child is owned by the parent's owner and inherits sharing from the parent. Program managers end up owning their own disbursements, and a clerk who can see a grant can work with its disbursements. It also means the integration user does not become the owner of 220,000 records - no ownership skew.

What you give up:

  • Disbursements can no longer have their own owner; if finance ever needs a clerk-level owner on the disbursement, that is a conversation to have now.
  • You cannot set an org-wide default on the child; visibility is controlled entirely at the grant.
  • Rollups recalculate on every child save, so bulk loads can contend on hot parent records.
  • Two of the ten rollup slots on Grant__c are consumed.

If the business later needs many-to-many (a disbursement split across grants), the answer is a junction object with two master-detail relationships, plus Apex or a rollup tool because standard rollups do not work across junctions.

2. Design the nightly load so the rollups, the uniqueness rule, and record locking do not become the next incident.

Read the worked answer

Key field: Legacy_Payment_Id__c, Text, marked External ID and Unique. Keep it case-sensitive - case-insensitive external IDs cannot use the standard index and slow down large upserts. Validate that the legacy system only emits one casing, or normalize in the integration before load.

Load pattern:

  • Upsert on the external ID; never match on Name or on the amount.
  • Do not set OwnerId on the child. On master-detail it is derived from the grant, which removes a whole class of skew and permission errors.
  • Keep batch size at 200 and do not run parallel loads against the same grants. Rollup recalculation takes a lock on the parent; two threads updating children of the same grant will collide with UNABLE_TO_LOCK_ROW. If the source file is ordered by grant, split it into chunks by grant range and run sequentially.
  • Load in a sandbox with a copy of production data first, then compare a control total: sum of disbursements per grant vs. the source system.

Failure handling:

  • Turn on the integration user's debug logging for one night and read the limits section of the log.
  • If the load is rejected by a validation rule, fix the data, not the rule - the rule is doing its job.
  • Record the reconciliation query you run the morning after, so the next person can repeat it.

3. Clerks report they can create a disbursement but immediately get an insufficient privileges error. What do you check, in order?

Read the worked answer

This is a security-model problem, not a data-model problem, and the order matters.

  1. Parent visibility. With grant OWD Private and no sharing rule, a clerk in a business unit may not be able to see the grant they are trying to attach to. Check the grant record's Sharing button and the user's record access before touching permissions.
  2. Object and field permissions. Confirm the clerk's permission set grants Create on Disbursement__c and the fields the page posts, and the level of access on Grant__c that your security review requires. Read-only on the parent plus create on the child is a usable combination; granting Modify All on grants to fix the error is not.
  3. Sharing design. If clerks must see grants, the cheapest fix is usually a criteria-based sharing rule on a Business_Unit__c field on Grant__c, shared to a public group per unit. Do not raise the grant OWD to Public Read Only - that over-shares 12,000 grant records to everyone and defeats the requirement.
  4. Only then look at whether a permission set was deployed with the wrong FLS.

Write the answer down as a runbook; this exact error will come back at the next reorg.