Print this page

Best Practices for Extracting UserAccessRecord in Wave Analytics

Knowledge Article Number 000233162
Description You may wish to control record access in Wave Analytics based on the UserRecordAccess object. This object is peculiar and has limitations that make it difficult to interact with. The default Salesforce Dataflow structure cannot extract data from the object. The workaround below may allow your org to use this object.

The following caveats apply:
  • Extracting data from UserAccessRecord is NOT recommended due to limitations and cost of pulling data from this object.
  • Any implementation will impact Bulk API in terms of daily batches limit being hit.
  • It is not possible to guarantee that this security approach will be efficient as it is not in line with the sharing/access/security strategy recommended for Wave. Please refer to the Wave Analytics Security Implementation Guide.

Consider the following implications if you choose to use this object:
  • Queries must be defined for a specific user and up to 200 RecordIds at a time.
  • This object represents an array of Users, Records, and Sharing tables/objects.
  • Large orgs could have millions of records for each object, making it difficult to extract efficiently.
Resolution Warning​ Salesforce Support cannot provide troubleshooting assistance for this workaround.


1. Create an apex class that extracts data from
  • UserRecordAccess looping through a list of UserIds and RecordIds
SELECT RecordId, HasReadAccess, HasTransferAccess, MaxAccessLevel 
FROM UserRecordAccess
WHERE UserId = [single ID]
AND RecordId = [single ID]      //or Record IN [list of IDs]
*** OR ***
  • Standard/Custom object for which access check is needed
SELECT Id, Name, UserRecordAccess.HasReadAccess FROM Account
2. Insert results/data into a Custom Object.
3. Use Apex Scheduler to create a Schedulable interface for the class.
4. Specify a schedule for the job to run (off-peak hours are recommended).
5. Wave dataflow runs extracting User Record Access data from the custom object and augments datasets as needed.

Sample code from Developer Forum to extract UserRecordAccess data:
List<Id> recIdLst = new List<Id>([Select ID FROM Account]);
MAP<ID,UserRecordAccess> usrAcsMap = new MAP<ID,UserRecordAccess>( [SELECT RecordId, HasReadAccess FROM UserRecordAccess WHERE UserId =:UserInfo.getUserId() AND RecordId IN :recIdLst] );


promote demote