# Overview

## Protect and Reuse Your Salesforce Data

GRAX is the leading provider of Salesforce data protection that helps businesses adapt faster by protecting their data and its value throughout its entire lifecycle from Salesforce data backup, archival, and reuse. With GRAX, customers can fully capture, own, access, manage, and reuse all of their Salesforce app data by simply backing it up or archiving it to their own cloud environment (AWS, Azure, GCP, and many others).

With GRAX, customers can:

* Own & access their backed up and archived data 24/7
* Capture record changes and restore to a specific Point-in-Time
* Reuse their Salesforce data easily for analytics, AI/ML, data warehousing, & more

## GRAX Products

Our products are designed to help our customers protect their Salesforce data, manage the data through its lifecycle, and turn that same dataset into value faster. The GRAX product suite is comprised of:

* [**Data Replication**](https://www.grax.com/products/data-replication-for-salesforce/)**:** Replicate Salesforce data into your cloud and use it anywhere
* [**Backup and Restore**](https://www.grax.com/products/backup-and-restore/)**:** Backup and recover data for business continuity
* [**Data Archive**](https://www.grax.com/products/data-archive/)**:** Reduce Salesforce storage costs & improve Salesforce performance without losing access to production data
* [**Time Machine**](https://www.grax.com/products/time-machine/)**:** Navigate changes in your cloud app data over time
* [**Data Lake**](https://www.grax.com/products/data-lake/)**:** Optimize & grow your business by making Salesforce data available for reuse anywhere via Parquet
* [**Data Lakehouse**](https://www.grax.com/products/data-lakehouse/)**:** Effortlessly build a data lakehouse on top of your built-in GRAX Data Lake to accelerate reporting, training, and acting on your Salesforce data
* [**GRAX Insights**](https://www.grax.com/products/grax-insights/)**:** Protect org health by tracking what matters — deletes, changes, and trends
* [**Sandbox Seeding**](https://www.grax.com/products/sandbox-seeding/)**:** Accelerate your development and testing environments by securely copying and anonymizing production data into sandboxes

GRAX products are compatible with:

* Salesforce Sales Cloud
* Salesforce Service Cloud
* Salesforce Community Cloud
* Salesforce Platform

{% hint style="success" %}
**Want to learn more?**

Explore GRAX products and packages by visiting [our pricing page](https://www.grax.com/pricing/).
{% endhint %}

## Running GRAX

GRAX offers GRAX Cloud, GRAX-managed, and self-managed deployments. Please refer to the following table to compare available options to find the best deployment solution for your business needs.

|                                    | GRAX-Managed                                                                                                                                     | Self-Managed                                                                                                | GRAX Cloud                                                                                                |
| ---------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------ | ----------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------- |
| Environment Hosting and Management | Customer-hosted                                                                                                                                  | Customer-hosted                                                                                             | GRAX-hosted                                                                                               |
| GRAX Application Management        | GRAX-managed                                                                                                                                     | Customer-managed                                                                                            | GRAX-managed                                                                                              |
| GRAX Application Updates           | GRAX-managed via Auto Updates                                                                                                                    | GRAX-managed via Auto Updates                                                                               | GRAX-managed via Auto Updates                                                                             |
| Data Ownership                     | Customer-owned                                                                                                                                   | Customer-owned                                                                                              | Customer-owned                                                                                            |
| Supported Environments             | AWS or Azure                                                                                                                                     | AWS, Azure, GCP, on-prem, Kubernetes, and others                                                            | AWS or Azure                                                                                              |
| Security Updates                   | Automated by GRAX                                                                                                                                | Manual by Customer                                                                                          | Automated by GRAX                                                                                         |
| Deployment Vehicles                | Deploy via Marketplace or GRAX Platform using certified templates                                                                                | Deploy via GRAX Binary using reference templates                                                            | Deploy via GRAX Platform                                                                                  |
| Data Storage                       | Unlimited                                                                                                                                        | Unlimited                                                                                                   | <p>5TB hosted</p><p>or</p><p>Bring your own storage for Unlimited data (<strong>recommended</strong>)</p> |
| Estimated Deployment Time          | \~10 minutes                                                                                                                                     | \~60 days                                                                                                   | \~10 minutes                                                                                              |
| Required Resources                 | Salesforce organization with System Administrator access, Dedicated AWS or Azure Account with AWS Cross Account Role or Static Azure Credentials | Salesforce organization with System Administrator access and a Cloud Team, Architecture and Security Review | Salesforce organization with System Administrator access                                                  |
| Standard GRAX Application Support  | ✔                                                                                                                                                | ✔                                                                                                           | ✔                                                                                                         |

### GRAX Cloud

GRAX Cloud is our fully-managed SaaS solution that enables the fastest path to protecting and reusing your Salesforce data. With GRAX Cloud, GRAX owns and operates all infrastructure in our secure cloud environment, eliminating the need for customers to provision or manage any cloud resources.

With GRAX Cloud, customers can:

* Get up and running in minutes with zero infrastructure setup
* Benefit from automatic updates, scaling, and optimizations
* Focus on leveraging their data, not managing infrastructure
* Access enterprise-grade security and compliance in a shared responsibility model

### GRAX-Managed

The GRAX Platform facilitates quick deployment of pre-built and tested infrastructure stacks across public cloud providers for running GRAX. These deployments are fully managed by GRAX via cross-account access policies.

With the [GRAX Platform](https://platform.grax.com), customers can:

* Deploy GRAX to any cloud account in minutes
* Scale their GRAX environment up and down easily
* Let GRAX handle upgrades, migrations, and updates

### Self-Managed

Organizations which choose to use self-managed deployments of GRAX are 100% responsible for design, deployment, and maintenance of their GRAX infrastructure. GRAX technical requirements and reference architecture are available to assist with the design process. Organizations are responsible for ensuring that their self-managed infrastructure meets the minimum requirements for GRAX to operate effectively. Minimum requirements to operate the GRAX product and utilization of underlying infrastructure resources are subject to change.

#### **Self-managed deployments include:**

* 60 days of email deployment assistance with:
  * GRAX Application, logs, and telemetry set up
  * GRAX Binary troubleshooting using GRAX Logs
  * High-level architecture guidance in relation to reference architecture and minimum requirements
* Choose and manage your own customer-owned infrastructure (AWS, Azure, GCP, on-prem, anywhere you’d like to run GRAX)
* Customer-managed GRAX Application
* External or GRAX access to infrastructure not required
* Ability to self-customize VPC, AMI, OS, system agents, and/or firewall
* Deployment registration with the GRAX Platform

#### **Self-managed deployments do NOT include:**

* Construction, management, and ongoing operating costs of all infrastructure
* Assistance with network failures, domain registration lapses, storage capacity issues, component failures, and improper configuration of the compute resources, which prevent software operation
* Any deviations from the 60-day implementation period

We recommend that you work with your internal cloud infrastructure team, cloud vendor support or TAM, or with GRAX System Integrator and/or Enterprise Support partners if you require assistance with any customizations that are not included.

## Getting Support

GRAX's award-winning support team is available by email and phone. For more information about our support team and process, see [here](https://documentation.grax.com/support/). See [here](/support/get-support) for guidance on contacting support. Standard support is available 9 AM - 6 PM EST Monday through Friday (excluding major US holidays).


# Backup

With GRAX Backup, you’re just a few clicks away from securely backing up your entire Salesforce org.

## Prerequisites

* Create an [integration user](/other/permissions-and-access/integration-user) and configure their permissions
* [Connect to Salesforce](/other/settings/connecting-salesforce)
* [Connect Storage](/other/settings/connecting-storage)

## How do I enable it?

To enable Backup:

* Navigate to the `Backup` tab within the GRAX Application
* You'll see the screen below, and will be prompted to choose one of the following options: `Start Backup to current bucket` or `Change the storage provider/bucket`

<figure><img src="/files/k11PIlG2Bvw0ikakgK9J" alt="" width="375"><figcaption></figcaption></figure>

When setting up Backup for the first time, GRAX starts by backing up object data in Salesforce, beginning with the oldest modified records and progressing to the most recently modified ones. Once the initial backup is complete, Backup seamlessly transitions to periodically capturing ongoing data changes.

{% hint style="info" %}
The time to complete backup of new data may vary based on amount of new data to backup, API limits, and system limits.
{% endhint %}

## How does it work?

Once the integration user is connected, GRAX:

* Periodically describes all the objects and schema in your org and adds them to the Backup system.
* Starts periodic jobs that pick an object and back up everything new or changed since the last backup.

## Dashboard and Monitoring

The Backup Dashboard in the GRAX Application serves as the central hub for tracking key metrics and statuses. It provides details into the total volume of data backed up, the time frames covered by secure backups, and the historical progress of Backup operations.

<figure><img src="/files/bnDkAZz39IoFwVPjdmfI" alt=""><figcaption><p>Healthy Backup Dashboard</p></figcaption></figure>

### Backup Toggle

You can easily control Backup behavior with the following options:

* `Backup Objects and Files`: Capture all available data objects
* `Backup Objects, Pause Files`: Exclude file data from the backup
* `Backups Paused`: Disable all backup operations

<figure><img src="/files/BThEIP9NNTBBxXNb8QI5" alt=""><figcaption><p>Backup Mode Selector</p></figcaption></figure>

### Backup Status

Additionally, the dashboard displays detailed status information, as outlined below:

* `Backfilling`: GRAX is backing up the history of your org, and at least one object has never been fully backed up
* `Behind`: All objects were fully backed up previously, but backup has since fallen behind for at least one object
* `Running Continuously`: GRAX is operating as expected and up to date on all objects within expected SLA
* `Paused`:Backup has been paused by a user for records, files, or both
* `Error`: An error has been encountered by the app while backing up data

<figure><img src="/files/Wvhip1h3GNixlMQWwxKo" alt=""><figcaption><p>Backup Dashboard Objects List</p></figcaption></figure>

Additionally, the Excluded Objects tab displays objects that are not being backed up due to being unsupported; you can read more about supported objects [here](/protect-data/backup/supported-objects).

<figure><img src="/files/QvqNgZHrRniPmndrLlh0" alt=""><figcaption><p>Backup Dashboard Excluded Objects List</p></figcaption></figure>

The dashboard also contains a list of files and objects being backed up along with record count and version count. Objects can have the following statuses:

* `Waiting`: object is caught up and waiting for new data
* `Running`: object is nearly caught up and backing up new data
* `Backfilling`: object is still backing up initial data
* `Paused`: object isn't being processed because Backup has been turned off
* `Excluded`: object isn't being processed because it has been explicitly excluded by the user
* `Unavailable`: object isn't being processed because GRAX has lost access to the object in Salesforce

{% hint style="info" %}
If the system encounters errors, Backup will display an Error status both for the entire process and the specific object affected. Additionally, a banner will appear on the dashboard with a link to the error summary page, where you can download a CSV containing detailed stack traces, if needed.
{% endhint %}

## Disabling an Object Backup

There are two methods for excluding objects from backup: one on the Salesforce side and one within the GRAX Application.

#### Preventing Backup via Salesforce Permissions

Backup is built to back up all possible Salesforce data by backing up every object the Integration User has permission to view. This design lets you manage what objects are backed up with standard Salesforce permissions and automatically backs up new custom objects or fields without the need to modify GRAX settings. If you don't want GRAX to back up an object or field because it isn't restorable, or isn't valuable to your data strategy, deny access to the object or field for the GRAX integration user.

#### Excluding Objects from Backup in GRAX

On the Settings page, under `General Settings`, you’ll find the `Backup Exclusions` field. Here, you can enter a comma-separated list of object API names to exclude from future backups. Once specified, these objects will be ignored in subsequent backups. However, if an object has already been backed up, it will still appear in the Objects list with an `Excluded` status.

## Frequently Asked Questions

#### Can I configure the backup schedule?

GRAX is designed to back up your entire Salesforce organization without complicated tools to configure objects, fields or schedules.

To achieve this, GRAX periodically scans your Salesforce organization for new data. If it finds new data, it then automatically schedules smaller jobs to backup new data while staying within Salesforce API limits, and within system limits to keep backups, archives, restores, searches, and Data Lake working as expected.

GRAX offers an option to change the period of scans between "daily" and "continuous."

* Daily Backup: scans for new data once a day
* Continuous Backup: scans for new data at a minimum of every hour

#### How do I use daily backup? How does it work?

[Contact GRAX Support](/support/get-support) to enable Daily Backup for your deployment.

In the backup dashboard, you’ll observe continuous activity during the initial backup and ‘backfill’ process. Afterward, daily scans will occur for each object, with activity distributed throughout the day.

No further configuration is necessary, or possible, on your part.

#### Why are formula fields showing outdated values?

While GRAX captures the definitions of formula fields as part of [metadata backups](https://documentation.grax.com/protect-data/auto-backup/salesforce-metadata-backup), it does not execute the formula logic when displaying field values or performing searches. Since formula fields are calculated in real time based on other field values and do not result in actual data changes, updates to these fields do not modify the `SystemModStamp`. As a result, changes to formula field values do not trigger the creation of a new record version. Therefore, the values displayed for formula fields reflect their state at the time of the most recent record backup.

#### What does "INSUFFICIENT\_ACCESS" mean?

*Example:* `salesforce INSUFFICIENT_ACCESS: insufficient access rights on cross-reference id`

Review your [Integration User permissions](/other/permissions-and-access/integration-user) for View All Data, View All Files and other required permissions. If the error occurs on Campaign or other marketing related objects, try enabling "Marketing User" for the integration user.

See the [User Fields reference doc](http://help.salesforce.com/HTViewHelpDoc?id=user_fields.htm\&language=en_US) for more information.

#### How does Backup handle records where a field is updated in Salesforce, but the record's "SystemModStamp" remains unchanged?

For the most part, each time a record is modified within Salesforce, Salesforce updates the `SystemModStamp` to reflect the date/time of the modification, however, there are certain fields (including, but not limited to formula fields), that when changed, do not result in an updated `SystemModStamp`. *This is a Salesforce limitation, not a GRAX limitation.*

Backup relies on a change in a record's `SystemModStamp` in order to identify, and therefore backup, new or changed data. If a record is being backed up for the first time, GRAX will backup the record with the value stored in Salesforce at the time of backup, but if the record is modified after the initial backup and Salesforce does not update the record's `SystemModStamp`, GRAX will not back up the change.

There are several documented workarounds detailing how to "trigger" a `SystemModStamp` update when fields that do not update the record's `SystemModStamp` are modified, one of which can be found [here](https://help.salesforce.com/s/articleView?id=000394815\&type=1).

#### What does "UNKNOWN\_EXCEPTION" mean?

{% code overflow="wrap" %}

```
UNKNOWN_EXCEPTION: sfdc.keystone.catalog.blobforce.KeystoneGetBlobFromStoresException: Failed to get a blob from all stores: orgId=00AbC000000DeM0 keyPrefix=05T entityId=05T2R000016VbmO blobId=0KF2R00002uQzDX extentId=F00D0b000000GaMp0KE2R00001MVoIw1 [...] there are no stores that currently contain the extent= F00D0b000000GaMp0KE2R00001MVoIw1, so we can't read it!)
```

{% endcode %}

An error has occurred within the Salesforce backend infrastructure, outside the scope of the GRAX Application. Please contact Salesforce support to open a case and report the issue.

{% hint style="info" %}
The Backup dashboard offers a CSV export of all errors to include with your support case.
{% endhint %}


# Backup API Usage

This article discusses estimated usage of the Salesforce REST API while using GRAX [Backup](/protect-data/backup). All figures provided here are estimates only and don't represent guaranteed figures for real-world usage.

## Backup Fundamentals

GRAX [Backup](/protect-data/backup) is a low-touch system that captures regular versions of all records in your Salesforce org, assembling a history for each record as it changes. To accomplish this, the system first captures all existing records in the org; it then scans at regular intervals to back up any new changes or records.

This means that the system queries a large amount of data from Salesforce early in the lifetime of your app. Regular, recurring backups draw only changed records and consist of small numbers of records in most orgs. The change between these two "modes" of the GRAX system is transparent to the user.

## API Usage During Initial Backup

Shortly after you enable Backup, the GRAX Application begins backing up data starting at the beginning of your org, if available. Through the Salesforce REST API, GRAX achieves the following usage function:

```
X = total original records in millions
Y = total original files in millions

API Calls To Backfill = (X + Y) * 3000 + 1000000 * Y
```

At the same time, GRAX estimates potential record throughput of 200 million per day. This all means that for an org with 1 billion records and 500 thousand files, GRAX would roughly consume 3.1 million REST API calls in just over 5 days (up to 600,000 each day).

## API Usage After Initial Backup

After GRAX has processed the history of your org, only changes and new records are captured for backup. This means the overall load on the system drops, and REST API usage follows. To estimate usage, we use a very similar function to the above, with modifications to the variables:

```
X = daily record creates and edits in millions
Y = daily file creates and edits in millions

API Calls Per Day = (X + Y) * 3000 + 1000000 * Y
```

The key here is that instead of capturing your whole org, GRAX captures changes or creations, commonly called "record turnover." Due to automation or global services, it's common for customers to have a turnover around 500 thousand records. Given this figure, we would then estimate daily API usage at 1,500 calls.

Note that the function above uses daily turnovers for a rough estimation - it's possible for a record to get updated more frequently throughout the day and get backed up in multiple recurring backups. This would increase daily usage for the same number of records, possibly many-fold if rate of change is high on certain records.

## API Limits and Protections

The Salesforce API has [limits on requests per 24-hour period](https://developer.salesforce.com/docs/atlas.en-us.salesforce_app_limits_cheatsheet.meta/salesforce_app_limits_cheatsheet/salesforce_app_limits_platform_api.htm). These limits are shared across all API consumers, including GRAX.

GRAX monitors your org's API usage and slows its Backup work if it reaches or exceeds 80%. Once usage falls back to 70%, the system resumes normal work.

## Caveats

The figures and functions expressed above are estimates. There are many factors that may affect how many calls Backup uses for a given set of data or in a given period of time. While the largest is of course the number of records, the content of each record can play a part as well.

For instance, an object definition that contains a large number of fields - especially long text fields - can significantly decrease the number of such records that can fit in each REST response. Those fields containing large amounts of data increase the number of utilized calls to back them up.

The are many specifics to each Salesforce dataset that can affect the usage of the REST API. If you are experiencing difficulties related to your org's Salesforce API limits or contention with other automation, please reach out to a GRAX representative or [GRAX Support](/support/get-support).


# Supported Objects

In general, GRAX supports backup of any Salesforce objects that meet all the following criteria:

1. Can be queried.
2. Has at least one 'audit date' field (`SystemModstamp`, `LastModifiedDate`, or `CreatedDate`), and that field is sortable.
3. Is available using the Salesforce API version GRAX uses (currently 65.0).
4. The running user (who is loading the list of objects and selecting which to back up) has at least read access to the object.

This covers most Salesforce objects.

{% hint style="warning" %}
This document only details which objects are able to be **backed up** with GRAX. Whether or not supported backup objects are able to be archived or restored is determined by Salesforce. Check out Salesforce's object specific documentation for more details.
{% endhint %}

## Unsupported Objects

Let's take a look at specific objects or categories of objects that GRAX doesn't currently support. Please note that these lists are not exhaustive and there may be additional objects that are unsupported. Typically, they aren't able to be queried or aren't fully supported by the API in some way. Please reach out to GRAX if you have questions about specific objects.

### Unsupported Standard Objects

```
AIApplication
AIDataDefinition
AIError
AIInsightAction
AIInsightFeedback
AIInsightReason
AIInsightSource
AIInsightValue
AIMetric
AIModel
AIModelDefinition
AIModelGraph
AIPredictionDefinition
AIRecordInsight
AIState
AcceptedEventRelation
AccountUserTerritory2View
ActivityMetric
ActivityMetricRollup
Address
AggregateResult
AppDefinition
AppTabMember
AssistantRecommendation
AssistantRecommendationShare
AssociatedLocation
AuraDefinitionBundleInfo
AuraDefinitionInfo
CaseStatus
ChatterMessageThread
CollaborationGroupRecord
ColorDefinition
ConfidenceThresholdConfig
ConfidenceThresholdCoverage
ContentBody
ContentDocumentSubscription
ContentFolderItem
ContentFolderLink
ContentFolderMember
ContentHubItem
ContentTagSubscription
ContentUserSubscription
ContentWorkspace
ContentWorkspaceDoc
ContentWorkspaceMember
ContentWorkspacePermission
ContentWorkspaceSubscription
ContractStatus
ContractStatusDeclinedEventRelation
CronJobDetail
DashboardComponent
DataStatistics
DataType
DatacloudAddress
DatacloudCompany
DatacloudContact
DatacloudDandBCompany
DecisionTable
DecisionTableDatasetLink
DeclinedEventRelation
DirectMessage
EinsteinDiscoveryModel
EmbeddedServiceDetail
EmbeddedServiceLabel
EntityDefinition
EntityParticle
EventBusSubscriber
EventWhoRelation
FeedAttachment
FeedTrackedChange
FieldDefinition
FieldSecurityClassification
FlexQueueItem
FlowDefinitionView
FlowTestView
FlowVariableView
FlowVersionView
FormulaFunction
FormulaFunctionAllowedType
FormulaFunctionCategory
GroupSubscription
IconDefinition
IdeaComment
IdpEventLog
KnowledgeArticle
KnowledgeArticleVersion
ListViewChartInstance
ListViewChartInstances
Location
MacroInstruction
MetadataPackageVersion
Name
NetworkUserHistoryRecent
NotificationMember
OauthToken
OrderStatus
OutgoingEmail
OutgoingEmailRelation
OwnerChangeOptionInfo
PartnerRole
Person
PicklistValueInfo
PlatformAction
PlatformEventUsageMetric
PredictionDefinition
PredictionDefinitionField
Publisher
RecentlyViewed
RecordRecommendation
RelationshipDomain
RelationshipInfo
S2XEventMap
S2XEventMapSelfServiceUser
SalesforceQuote
SearchLayout
SelfServiceUser
ServiceAppointmentStatus
ShiftStatus
Site
SiteDetail
SolutionStatus
TabDefinition
TaskPriority
TaskStatus
TaskWhoRelation
TenantSecret
ThirdPartyAccountLink
TwoFactorInfo
TwoFactorTempCode
UndecidedEventRelation
UserAppMenuCustomization
UserAppMenuItem
UserEntityAccess
UserFieldAccess
UserPermissionAccess
UserRecordAccess
UserRecordAccessTaskStatus
UserSetupEntityAccess
VisualizationPlugin
VisualizationResource
VisualizationType
Vote
WorkOrderLineItemStatus
WorkOrderStatus
```

### Unsupported Standard Big Objects

```
AnalyticsBotSession
ApiEvent
BackgroundOperationResult
BotAnalytics
BotEventLog
FieldHistoryArchive
IdentityVerificationEvent
LightningUriEvent
ListViewEvent
LoginAsEvent
LoginEvent
LoginHistory
LogoutEvent
RecordActionHistory
ReportEvent
UriEvent
```

### Unsupported Standard Objects With Prefix

```
Apex
PartnerNetwork
```

### Unsupported Standard Objects With Suffix

```
EventStore
Feed
Share
__ViewStat
__VoteStat
__b (big objects)
__mdt (custom metadata types)
__x (external objects)
_hd (historical trending objects)
```

### Unsupported Custom Objects With Prefix

```
grax
```

## Feature-Specific Objects

#### Chatter / Feed

GRAX doesn't support `Feed` objects within an object backup.

#### Custom Metadata Types

GRAX doesn't support backup of custom metadata types.

#### Custom Settings

Custom Setting objects should appear in the GRAX backup list, provided they aren't "protected." Please note that some custom setting objects may not be supported for archiving or restoring, even if they are being backed up. [Click here](https://help.salesforce.com/articleView?id=cs_define.htm\&type=5) for more information on custom settings.

#### Einstein Objects

GRAX doesn't support backup of Einstein objects.

#### **FeedAttachment**

`FeedAttachment` doesn't have an audit date field and thus isn't supported. This object is a junction between `FeedItem` and `ContentVersion`. You are still able to back up the File that is posted in the Chatter Feed as long as that file is also linked to the record via `ContentDocumentLink`, which is supported and available to select in the hierarchy.

#### **File Objects**

Certain Salesforce objects contain binary fields with base64 encoded data (that is files). GRAX supports the backup of `Attachments`, Content (via the linkages amongst `ContentDocument`, `ContentVersion`, and `ContentDocumentLink`), and `EventLogFiles`. For any other objects that may contain these base64 fields, GRAX may support backing up other data fields, besides the binary, per the rules mentioned above.

#### History Objects

GRAX supports the backup of `History` objects, such as `CaseHistory` and `OpportunityFieldHistory`, in addition to custom `History` objects. To enable backup of these objects, please contact [GRAX Support](/support/get-support).

#### Knowledge

GRAX supports the backup of both the Classic and Lightning `Knowledge` object model, which revolve around objects ending in either `ka` or `kav`. `VoteStat` and `ViewStat` objects aren't supported, as indicated above.

#### Tags

`Tag` objects are supported. For object backups, you will see a backup type category if you have tags enabled in your org.


# Delete Tracking

Delete Tracking gives users the ability to track records that have been deleted through the Salesforce UI, ETL, etc. This means that your GRAX dataset stays up-to-date as users, or automation, remove records from your Salesforce org in between backups.

## What is it?

Delete Tracking is an automated GRAX process that routinely monitors all backed-up objects for records deleted directly in Salesforce.

## How do I enable it?

Delete Tracking is enabled by default for all customers to run once per hour.

## How does it work?

Through [this](mailto:undefined) Salesforce API, Delete Tracking retrieves records deleted directly in Salesforce since the last scan, and GRAX marks any matches as `Deleted`.

{% hint style="warning" %}
GRAX only tracks deletes for records that have already been backed up.
{% endhint %}

To ensure record status accuracy, GRAX also performs a trailing scan, that goes beyond the last scan window, to verify whether each record is still active in Salesforce. Records found inactive are flagged as `Deleted` at the time of detection.

The trailing scan was introduced on August 26, 2025, which may result in a noticeable spike in deleted records around that date. An indicator on the Delete Tracking graph and a tooltip at the top of the page provide additional details.

<figure><img src="/files/w9zgeepRbRqvaMsl3tMw" alt=""><figcaption></figcaption></figure>

{% hint style="warning" %}
**Unsupported Objects**

Salesforce doesn't support Content objects (`ContentDocument`, `ContentVersion`, or `ContentDocumentLink`) for this type of delete tracking. The `Attachment` object, however, is supported.

[Click here](https://developer.salesforce.com/docs/atlas.en-us.api.meta/api/object-specific_requirements_for_data_replication.htm) to see more detailed requirements of objects that Salesforce allows to be tracked as deleted in this manner, which allows you to determine all objects in your org that can be tracked for deletions by GRAX.
{% endhint %}

## Anomaly Detection

{% hint style="info" %}
Anomaly Detection is currently a pilot feature within GRAX Insights. You’ll be notified as soon as it becomes available in your environment.
{% endhint %}

When GRAX detects an unusually high number of deletes—calculated using a threshold above the [median absolute deviation (MAD)](https://en.wikipedia.org/wiki/Median_absolute_deviation) - it will send you a notification for review.

## Frequently Asked Questions

### Can I adjust the frequency at which Delete Tracking runs?

Yes! The Delete Tracking interval can be adjusted by navigating to `Settings` > `General Settings` > `Delete Tracking Interval`.


# Salesforce Metadata Backup

{% hint style="warning" %}
As of April 2025, GRAX only performs incremental metadata backups. GRAX will take a snapshot of any new files or ones that have changed since the previous backup. For example, if a file was added on Monday, modified on Wednesday, and rolled back to the original version on Friday, GRAX will only save the three versions from Monday, Wednesday, and Friday.
{% endhint %}

GRAX supports periodic backup of all possible metadata objects from Salesforce. GRAX stores your metadata in the customer-owned storage solution (S3, Azure, etc), and the version history is available in the GRAX Diagnostics and Tools page.

## Configuration / Setup

By default, GRAX checks for any new or changed metadata once per day. To change the metadata backup frequency, simply select a backup interval in the `General Settings` tab.

<figure><img src="/files/KBoOqaP8nTKqv62ENbcD" alt="" width="563"><figcaption><p>Metadata Backup Interval Setting</p></figcaption></figure>

<img src="/files/PL34bSDAwCBrbZZr55Q8" alt="Metadata Backup Interval Selection Window" width="432">

## Working with Metadata Backups

The metadata backups are stored in the customer-owned storage solution (S3, Azure etc) and can be accessed with the Salesforce Metadata viewer in the GRAX Diagnostics and Tools page.

<figure><img src="/files/asQlgwQVjB3T7AuS47yQ" alt=""><figcaption><p>Getting to GRAX Tools List</p></figcaption></figure>

<figure><img src="/files/FM39ecKD6DZXQUrPwVl0" alt=""><figcaption><p>Metadata Explorer in GRAX Tools List</p></figcaption></figure>

Metadata files are grouped by Salesforce Object Type

<figure><img src="/files/GYGwUD0z1Egz0NsHslzL" alt=""><figcaption><p>Metadata Object Selection</p></figcaption></figure>

### Viewing Metadata File contents

To view the contents of a metadata file version, click the Visibility / Eye icon for the desired version, the file will be displayed above the version list.

<figure><img src="/files/MqEDP5m99ttaWt6Rhuva" alt=""><figcaption><p>View Metadata Object Version</p></figcaption></figure>

### Comparing Metadata Versions

To see the differences between 2 versions of a metadata file:

1. Click the "Compare" icons to select the 2 versions you want to diff.
2. Once 2 versions have been selected the "Compare" button above the version list will be enabled. Click it to open a list of the changes between the 2 selected versions.

<figure><img src="/files/RGIMZZCH67D7y3ppimg0" alt=""><figcaption><p>Metadata Object Version Diff View</p></figcaption></figure>

### Downloading Metadata Versions

To download the contents of a metadata file version, click the "Download" icon for the desired version.

<figure><img src="/files/BDPso3rEG4KQOYCXIqJ5" alt=""><figcaption><p>Metadata Object Version Download</p></figcaption></figure>

## Frequently Asked Questions

### Which Salesforce API is used to determine what metadata is backed up?

We utilize the [describeMetadata()](https://developer.salesforce.com/docs/atlas.en-us.api_meta.meta/api_meta/meta_describe.htm) API.

Additional documentation on Salesforce's metadata API can be found [here](https://developer.salesforce.com/docs/atlas.en-us.api_meta.meta/api_meta/meta_intro.htm).

### Why does the Salesforce Metadata Tool in GRAX not show metadata for all of my objects?

This [describeMetadata()](https://developer.salesforce.com/docs/atlas.en-us.api_meta.meta/api_meta/meta_describe.htm) API call retrieves the metadata that describes your organization. This information includes Apex classes and triggers, custom objects, custom fields on standard objects, tab sets that define an app, and many other metadata types. **Standard objects without custom fields are not included in this data.**


# Missing Field Permissions

To ensure comprehensive backups, GRAX requires access to all object fields you wish to include. The `Missing Field Permissions` tool helps you quickly identify any object fields the GRAX Integration user lacks access to. Additionally, it offers an auto fix functionality that can automatically resolve any missing field permission issues for you.

## Where is the `Missing Field Permissions` tool located?

The `Missing Field Permissions` tool can be found by navigating to `Settings` > `Diagnostics and Tools` > `Missing Field Permissions` within the GRAX Application.

## How does it work?

Several times a day, GRAX automatically scans all of the objects we have access to for missing field permissions. If GRAX identifies one or more objects with missing field permissions, a yellow banner will appear at the top of the Application.

![Missing Field Permissions Banner](/files/7YdRYEKeZoJ9cgBHMFv4)

After clicking on the `Missing Field Permissions` link in the banner, you'll be redirected to the `Missing Field Permissions` tool, where you'll see a pie chart and a list, detailing each object's missing field permissions status.

![Missing Field Permissions Page](/files/6GvEvX3rBStsytfers7c)

To home in on the objects with missing field permissions:

* Click on the icon to the right of the `Object Status` column
* Deselect `OK` and select `Missing Field`
* Click `Apply`

![Sorting/Filtering Missing Field Permissions](/files/hUvqdMh1tDxG0lUGzYMe)

![Sorting/Filtering Missing Field Permissions](/files/FMALj7PasI2dMKs54l9R)

#### `Scan Now` Button

Clicking the `Scan Now` button, at the top of the `Missing Field Permissions` tool page, scans all objects (that GRAX has access to) to determine if there are any missing field permissions. Scans are automatically run several times a day, but the `Scan Now` button allows you to identify missing field permissions at the time of the button click.

{% hint style="info" %}
The scan may take several minutes to complete.
{% endhint %}

#### `Auto Fix Permission Issues` Button

The `Auto Fix Permission Issues` button, at the top of the `Missing Field Permissions` tool page, will attempt to auto fix any missing field permissions at the time of the button click.

To ensure the success of the auto fix functionality, the GRAX Integration user will need the following Salesforce \`System Permissions':

* `Author Apex`
* `Customize Application`
* `Manage Profiles and Permission Sets`

#### `Download CSV` Button

Clicking the `Download CSV` button, at the top of the `Missing Field Permissions` tool page, will download a list of all your objects and their corresponding missing field permissions status.

## How do I fix objects with missing field permissions?

There are 2 ways that you can fix objects with missing field permissions:

### `Auto Fix Missing Field Permissions Issues` Setting

The `Auto Fix Missing Field Permissions Issues` setting allows GRAX to automatically fix missing field permissions for you, without requiring you to click the [Auto Fix Permissions Issue button](#auto-fix-permission-issues-button). When enabled, the auto fix functionality will run several times a day (after each scan for missing field permissions) and automatically fix the missing field permissions.

In order to utilize this functionality, you'll need to:

* Ensure that the `Auto Fix Missing Field Permissions Issues` setting is enabled. To enable:
  * Navigate to `Settings` > `General Settings` > `Auto Fix Missing Field Permissions Issues`
  * Click the pencil icon to the right of `Auto Fix Missing Field Permissions Issues`
  * Select `Enabled` from the dropdown menu
  * Click `Save`.
* Ensure that the GRAX Integration user has the following Salesforce `System Permissions`:
  * `Author Apex`
  * `Customize Application`
  * `Manage Profiles and Permission Sets`

### Manually Fix Missing Field Permissions

To manually fix objects with missing field permissions, follow the steps below:

* [Navigate to the `Missing Field Permissions` tool](#where-is-the-missing-field-permissions-tool-located)
* Click on an object name. You'll be redirected to the Salesforce `Object Settings` page for the specific object you clicked on
* Click `Edit` at the top of the page
* Check the boxes next to the field that you'd like to grant access to (`Read` access is necessary for backup, `Edit` access is necessary for archive and restore)
* Click `Save`

Repeat this process for each object until GRAX has access to all of the fields that you want to be included in your backup.

## Frequently Asked Questions

#### I am trying to manually fix missing field permission issues, but the object name is not clickable - why?

In order for the object names to be clickable, the GRAX Integration user will need to have the [`GRAX Integration User` permission set](/other/permissions-and-access/integration-user) assigned within Salesforce.

#### Why are there suddenly missing field permissions?

Check with your Salesforce Admin team to identify if there have been any recent changes that may have impacted the GRAX Integration user or the impacted objects.

#### How does GRAX fix missing field permissions?

GRAX uses Apex scripts to automatically (via the `Auto Fix Permission Issues` button, or the `Auto Fix Missing Field Permissions Issues` setting) fix missing field permissions. To view the corrective Apex script for each object, check the box next to the Object name and click the `Show Apex Script for Checked` button at the bottom of the screen.

#### How do I resolve an error that GRAX encountered an error setting permissions?

GRAX may be unable to Auto Fix Permissions for several reasons, including:

* The GRAX Integration user doesn't have sufficient access. Check that GRAX has the `Author Apex`, `Customize Application`, and `Manage Profiles and Permission Sets` permissions enabled
* The Objects or Fields we are attempting to set grant access to require an additional Salesforce License.
  * Follow the [Manually Fix Missing Field Permissions](#manually-fix-missing-field-permissions) steps above
  * After clicking `Save` Salesforce will provide additional information on the prerequisites to grant access to these fields
  * Review the Salesforce Requirements and grant GRAX access before trying again.
  * If you determine that you don't want GRAX to access these field, click on the `Missing Fields` link in the `Missing Field Permissions` report to ignore the remaining fields


# Viewing Records

You can access a GRAX record view page by selecting a record ID from a job execution summary, search results, or an object record list, or by using the in-app search bar. Upon navigating to the record view page, the interface will typically display the following layout:

<figure><img src="/files/bzmSlK8xRqe8KeZmAXlH" alt=""><figcaption><p>Record view page</p></figcaption></figure>

The object name and record name are displayed at the top left of the page, followed by version information (if applicable) and audit field data. On the top right, users will find options to download record information and access a menu containing additional actions.

## Record Overview

The overview section offers a quick glance at all key information regarding the record. You'll typically see the following information:

* `Id` - this is the standard 18 digit Salesforce record identifier
* `Name` - this is the standard Salesforce `Name` field (if applicable)
* `Created` - this is the standard Salesforce CreatedDate field
* `Modified` - this is the standard Salesforce LastModifiedDate field
* `Deleted At` - this is a GRAX system field that shows when GRAX captured a record as archived or deleted (if applicable)
* `Delete Source` - this is a GRAX system field that shows whether the delete source was via GRAX archive job or manual Salesforce delete picked up via [Delete Tracking](/protect-data/backup/delete-tracking) (if applicable)
* `Status` - this will show if the record is live, deleted or archived

{% hint style="info" %}
When we use the term `archived` for a record, it means the record was removed from Salesforce via a GRAX Archive job. You would see the GRAX system field `Delete Source` on the record as `grax`.

When we use the term `deleted` for a record, it means the record was removed/deleted from Salesforce by a non-GRAX actor. You would see the GRAX system field `Delete Source` on the record as `salesforce`.
{% endhint %}

## Action Buttons

In the upper right corner of this page, there are three vertical dots which expand to provide some action buttons. These include:

* **View in Salesforce** - If the record in GRAX is believed to be live (not tracked as archived/deleted), there will be a `View in Salesforce` button, which takes you to the record in the linked Salesforce org. Note that the availability of this button is based on the most recent version of that record captured in GRAX.
* **Sync Record** - This will sync the most recent updates to Backup; this can be used if updates are made in between the standard sync times and the change needs to be reflected immediately.
* **Archive** - If the record is live, this will bring you to the Archive job setup page to start an archive job for this record.
* **Restore/Restore Children** - If the record is tracked as archived/deleted, the page has a Restore button that launches the restoration flow.
* **Seed** - The record can be seeded into a sandbox and this will start the configuration process for that action.
* **Lock** - This will lock the record in GRAX, preventing it from being Purged.

## Versions

You will see how many versions of the record have been backed up, and you can navigate through all captured versions of this record. The full lifecycle of this record is tracked here, including when a record was archived and if it was ever restored. Restoring a record generates a brand new Salesforce ID, but GRAX captures that and links it back to the "original" record to keep a full lineage.

You can view the data by navigating to each version within the record detail page, or by clicking the number of versions, which will show a list of all versions and an option to compare the fields that have been changed in each one.

<figure><img src="/files/Wuo1pNWd38jA4gbUHzqc" alt=""><figcaption><p>Record Versions List</p></figcaption></figure>

<figure><img src="/files/45Vz6aYiP6gS7Q0FqPrT" alt=""><figcaption><p>Record Versions Comparison</p></figcaption></figure>

## Hierarchy Graph

Here you can see all the relationships beneath this record in the Salesforce hierarchy. You can click on any node to view the full set of related records and further click into one of those child records if desired.

![Hierarchy Graph](/files/y4naUshdEIuC9VrMExlj)

## Fields

This component is beneath the hierarchy graph and displays all fields backed up for this record and for the particular version you are viewing. You can switch between standard and compact views with the `view toggle` <img src="/files/EztQ772OwN2RrBfJt6Qp" alt="" data-size="line">; use the `Filter Fields` input box <img src="/files/OdXBUhwnYCdZIJiM97a2" alt="" data-size="line"> to easily filter down to fields that you may be looking for in a long list. The filter scans field labels and API names (but does not search the field values).

Additionally, reference/lookup fields are hyperlinked. You can click to be taken to the reference field's record view page, assuming it exists in GRAX.

{% hint style="info" %}
The fields shown here respect Salesforce field-level security. Specifically, users log into GRAX via Salesforce Single Sign-On. Thus, that user's profile (or permission sets) must grant at least view access to the field for it to display here. Currently, GRAX doesn't make an exception for "View all Data" permissions in Salesforce.
{% endhint %}


# Viewing Files

When a record is associated with files in Salesforce, GRAX will render a section named "Files" to represent them, showing their name and size - as well as buttons to view and download them:

<figure><img src="/files/8Cyy1aPwJUHxAP6qdcUb" alt=""><figcaption><p>Files Graph Breakdown</p></figcaption></figure>

This shows up for records of objects that contain files:

* `Attachment`
* `ContentVersion`
* `EventLogFile`

As well as records associated with them, be it via the `Attachment` reference or via a `ContentDocumentLink` . This means if you're looking at an email that has attachments, the corresponding files should show up right there.

Internally, files are stored in the provided bucket under:

```
grax/audittrail/salesforce/$ORG_ID/$OBJECT/$RECORD_ID/files/$RECORD_ID
```

You can also use the [GRAX API to view files related to a record and download their contents](https://api.grax.com/#tag/record-files).


# Archive

{% hint style="danger" %}
Before you can archive data you must enable [Backup](/protect-data/backup). Archiving data is a destructive action. Salesforce's Cascade Delete mechanisms and trigger automation may cause more data than you expect to be destroyed. Backup is the best way to guarantee all deleted data, whether deleted by GRAX archives or from any other Salesforce action, is protected in GRAX.
{% endhint %}

GRAX Archive provides you tooling to easily delete data from Salesforce with confidence.

## What is it?

GRAX Archive allows you to safely delete records from Salesforce while ensuring they remain fully accessible in GRAX for search, visualization, and restore. Unlike a native Salesforce delete, GRAX is built to address common concerns around deletion:

* Auditability – complete visibility into what was deleted, when, and by whom.
* Capacity planning – reduce Salesforce storage usage while retaining access to data.

The foundation of archiving is Backup. Backup guarantees that GRAX has the latest version of every record before archiving. This means things like triggers and cascade deletes aren't going to unexpectedly cause data loss.

## How does it work?

### Step-by-Step Process

1. The GRAX integration user (with delete permissions in Salesforce, typically `Modify All Data`) initiates an archive.
2. GRAX:
   * Identifies the parent object(s) you want to delete.
   * Inspects the object schema to detect child relationships.
   * Prepares a preview (graph or list view) of all records to be deleted.
   * Applies your selected verification method.
   * Issues cascade delete API calls to Salesforce to remove the records.
   * Provides a summary report (counts, errors, orphan cleanup).
3. GRAX updates its index so those records remain available for search and restore.

### What gets deleted?

* Parent and Child Records – Salesforce cascade delete rules determine which children are removed (e.g., deleting a `Case` also deletes related `Tasks` and `Events`).
  * Master-Detail relationships are deleted automatically with their parent record (shown in blue in graph view on Configure step).
  * Lookup relationships are NOT automatically deleted by default (shown in grey in graph view on Configure step).
* Files – GRAX proactively deletes orphaned `ContentDocument` records and files that Salesforce leaves behind, keeping your environment clean.
* Content Links – `ContentDocument`, `ContentVersion`, and `ContentDocumentLink` are only deleted once their final parent record has been archived. If still linked elsewhere, they remain intact.

### Managing Lookup Relationships

By default, GRAX only considers master-detail relationships to be deleted with their parent record. If your archive includes records with lookup child relationships, you have the option to include those lookups in the archive as well.

To include lookup relationships in your archive:

* Navigate to the Configure step before archiving.
* For each lookup child relationship, click the Review Relationships icon underneath the graph view to identify any records at risk of being orphaned.
* GRAX will display a warning if orphaned records are detected when the icon is clicked. A red dot on the icon will be visible if there is a warning.
  * For example: "Case Relationships – By default GRAX only considers master-detail relationships to be deleted with their parent record. This means the following lookup relationships would leave records orphaned. Check them to include in this archive: Case\_\_c (Case\_Responses\_\_r)"
* Select the lookup relationships you want to include in the archive.

#### Including Additional Parent Objects

The Relationships tab in the List view allows you to select unselected Parent Objects, enabling you to include additional optional objects in your archive. This is useful when you want to expand your archive scope beyond the primary object selection.

### Verification Methods

* `Verify records individually with Salesforce` – safest method; checks every record via SOQL. Recommended when data might still be changing.
* `Verify Backup is current` – faster; relies on Backup snapshots. Recommended for older, stable data sets (e.g., historical `EmailMessages`).

### Archive Sources

You can select data to archive in several ways:

| Source Type      | Description                                                                                                                                                                |
| ---------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `Search`         | Use GRAX Global Search to filter by object, record status, dates, and fields.                                                                                              |
| `Report`         | Run a Salesforce tabular report stored in a GRAX-accessible folder. **The folder, or Report Name, must contain `GRAX` and the report must be < 100k rows or 100 columns.** |
| `CSV`            | Upload a CSV with an Id column. **File size ≤500 MB; first batch ≤20,000 records.** Larger sets can be processed with Auto Archive.                                        |
| `Record IDs`     | Paste **up to 200 record IDs** for direct deletion.                                                                                                                        |
| `Query Template` | Use predefined templates for objects like `Case`, `EmailMessage`, `Task`, or `ContentDocumentLink`.                                                                        |
| `Query WHERE`    | Provide only the WHERE clause; GRAX constructs the full query. Supports performance tuning.                                                                                |

### Archive Options

* `Skip Objects` – Will skip specific objects so they aren’t included in the archive.
* `Archive blocking children` – force delete even if child records would normally block parent deletion. Without this option you'll see `DELETE_FAILED` errors for these records.
* `Delete whole email threads` - When deleting an `EmailMessage` record, this ensures we also delete every other email in the thread, even if they don't match your archive criteria. For example, if a single EmailMessage in a thread is related to a Case that meets your criteria, instead of just deleting that one EmailMessage, it deletes the entire thread associated with that EmailMessage.
* `Hard Delete` - Also deletes records from the recycle bin.

Additionally, the [Settings page](/other/settings) includes global options that apply to all archive operations.

### Auto Archive Behavior

* Any successful manual archive can be converted into an Auto Archive job, which runs continuously in the background.
* If records repeatedly fail to delete (e.g., permission or schema issues), GRAX automatically delays retries (up to 24 hours) until the issues are resolved.
* Job runs are tracked, including number of records processed, errors, and skipped entries.

### Archive Statuses

#### Record Statuses

|              |                                                                                                                                                                                                                   |
| ------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `Successful` | Record was successfully archived.                                                                                                                                                                                 |
| `Pending`    | Record is pending because it’s being archived or blocked by an error in a parent record. Blocked records stay pending until they’re retried individually or the parent error is resolved in a future archive job. |
| `Error`      | Record was not archived due to an error; this could be Salesforce or GRAX related and the error message for the record will need to be reviewed to find out more information.                                     |
| `Skipped`    | Record was not archived due to it either being previously deleted within Salesforce or being automatically archived with a linked parent record as is the case with `ContentVersion` records.                     |

#### Job Statuses

|              |                                                                                |
| ------------ | ------------------------------------------------------------------------------ |
| `Completed`  | Job successfully finished and archived records.                                |
| `Pending`    | Job is ready to run and is pending execution.                                  |
| `Setting Up` | Job is querying and loading records to set up the job.                         |
| `Sustaining` | Job is waiting for new records that match the job criteria to be archived.     |
| `Error`      | Job did not complete and did not archive any records.                          |
| `Warning`    | Job has at least one record that was not archived OR did not find any results. |
| `Disabled`   | Job has been manually deactivated and is not currently running.                |

## How do I enable it?

1. [Enable Backup](https://documentation.grax.com/protect-data/backup)
   * Backup must be enabled before Archive can run.
2. Test with a single record
   * Archive and restore one `EmailMessage` first. This helps expose any Salesforce permission or object access issues before larger jobs.
3. Perform your first archive
   * Open the Record Viewer → find an `EmailMessage`.
   * Click `Archive`.
   * Keep the default option `Verify records individually with Salesforce.`
   * Review the confirmation plan (shows parent and child records, plus files slated for deletion).
   * Click `Execute`. GRAX will:
     * Verify records and related data are backed up.
     * Delete the records and any orphaned files in Salesforce.
     * Update GRAX to reflect the latest status.
4. Configure archive criteria
   * Use `Search`, `Report`, `CSV`, or query methods to define what to archive next.
   * Set verification and archive options based on your data’s stability.
5. Enable Auto Archive (optional)
   * Convert a successful manual job into Auto Archive to continuously archive new eligible records.
6. Monitor dashboards & errors
   * Use the Archive Dashboard to track overall archive activity, storage reclaimed, and error trends.
   * Review statuses to troubleshoot skipped or errored records.

## Addressing Auto Archive Job Delays & Record Errors

When errors occur during archiving, GRAX automatically adjusts the schedule to avoid repeatedly retrying the same failing records.

* Each record encountering an error may increase the delay before the next archive run.
* The maximum delay is **1 day**.
* Once the errors are resolved, archiving will gradually resume at normal speed.

If you notice your Auto Archive is only running once per day, this usually means a set of records are repeatedly failing. Check for any record errors in the archive job and note the corresponding error message. Fixing or removing those records in Salesforce will allow archiving to speed up again.

You can filter to records that have an error status by navigating to the Archive job in question and switching the record filter to `Error` :

<figure><img src="/files/VWs96YfHnSnbGvcqYCS4" alt=""><figcaption></figcaption></figure>

## Archive Use Cases

Deleting Salesforce data without disrupting your dataset or user experience can be challenging. The complexity of Salesforce schemas, relationships, and validation rules makes archiving and restoring higher-level objects difficult.

For example, deleting a single `Account` can trigger cascade deletes of many child records, and other objects that reference the `Account` or its children may block the deletion until updated or removed.

To avoid these issues, break your archive plan into smaller steps and work bottom-up in the data model. For standard Salesforce objects, we recommend archiving in this order:

1. `EmailMessage` + `Attachments`
2. `Task`
3. `Case`
4. `Opportunity`

{% hint style="warning" %}
We strongly discourage archiving top-down - for example, trying to delete an `Opportunity` and expecting all related `Cases`, `Tasks`, and `EmailMessages` to be removed automatically. This approach often leads to validation errors and incomplete deletions.
{% endhint %}

### Archiving EmailMessage + Attachments

`EmailMessages` and their `Attachments` are the simplest and most effective records to archive. In most Salesforce orgs, `EmailMessages` account for the majority of object storage, and their attachments contribute significantly to file storage. Since `EmailMessages` sit at the bottom of the data hierarchy, they have few relationships that could trigger validation errors, making them safe and straightforward to archive.

#### Recommended Approach:

* Configure an archive for `EmailMessages` only.
* Leave objects like `Case` in Salesforce and use [GRAX Lightning Web Components](https://documentation.grax.com/reuse-data/managed-package/second-generation/features) to display archived `EmailMessages` directly on `Case` records.

### Archiving Tasks

Tasks are another simple and effective target for archiving, helping reduce storage and meet data compliance requirements. Many Salesforce orgs have old `Task` records that no longer need to remain live.

Recommended Approach:

* Archive `Task` records only.
* Leave objects like `Case` in Salesforce and use [GRAX Lightning Web Components](https://documentation.grax.com/reuse-data/managed-package/second-generation/features) to display archived `Task` records directly on `Case` records.

### Archiving Records with Related Content Documents

Salesforce manages files using three key objects:

1. `ContentDocument` – represents the file itself.
2. `ContentVersion` – child of `ContentDocument`; tracks all file versions.
3. `ContentDocumentLink` – connects the file to records, users, or libraries.

A single `ContentDocument` can be linked to multiple records via multiple `ContentDocumentLinks`. GRAX will only archive the `ContentDocument` and `ContentVersion` after the last linked record is archived or deleted.

Scenarios where only the ContentDocumentLink is archived:

* The `ContentDocument` is in a Content Library (linked to a `ContentWorkspace`).
* The `ContentDocument` is linked to multiple records, and at least one record remains active.
* Orphaned `ContentDocuments` (all linked records deleted or archived) can be Auto Archived.

{% hint style="warning" %}
Directly archiving a `ContentDocument` removes all related `ContentVersions` and `ContentDocumentLinks`.
{% endhint %}

## Frequently Asked Questions

### Can records that are archived by GRAX be recovered from the Salesforce recycle bin?

No - Archived records are "hard deleted" by GRAX. Archived records can be recovered by using [Restore](/protect-data/restore).

### **Why is my Auto Archive job not picking up new matching records?**

When an archive job is initiated from the Global Search module, any subsequent Auto Archive job will run only as many times as necessary to process the initial batch of search results; it will not continue to search for or archive newly matching records.

To ensure that an Auto Archive job consistently captures new records based on defined search criteria, it must be configured using the *Search* source within the *Archive* module.

### Why was my Archive job automatically marked as ‘Disabled’?

Archive jobs that fail to identify new records for five consecutive weeks are automatically disabled.

Disabled jobs can be located by navigating to the `Archive` tab and clicking `View Disabled`.


# Restore

The GRAX Restore feature gives users the ability to update selected records to an earlier state which was backed up by GRAX, as well as the option to restore previously deleted records back into Salesforce. This is crucial for users who have a catastrophic event and need to restore records, but it isn't the only challenge Salesforce Administrators face. What about a data corruption that only affects a few fields, or one that has escaped the notice of the team for a few days or weeks? How would the administrator mass restore thousands, or a hundred thousand records, to a version of this record from a few weeks ago?

With GRAX Restore, administrators have the ability to restore individual field level changes, or multiple fields, to any point in time in the history of the GRAX Backup.

## Restore in the GRAX Application

Open the GRAX Application and navigate to the Restore tab.

The Restore home page shows a list of all the previously configured batch and single Restore executions and the different statuses that they can be in.

<figure><img src="/files/B4FIvvnc5AaRIYFJ27Vw" alt=""><figcaption><p>Restore Jobs Page</p></figcaption></figure>

### Possible Restore Statuses

| Status     | Description                                                                                                                                      |
| ---------- | ------------------------------------------------------------------------------------------------------------------------------------------------ |
| Pending    | A Restore job is in `Pending` status if it's waiting for other job archive/restore jobs to finish.                                               |
| Setting Up | A Restore is in `Setting Up` status when further configuration is required before the job can be launched.                                       |
| Ready      | A Restore job is `Ready` when it has loaded data from the source and validated which records of this data set exist for the specified execution. |
| Queued     | A Restore job is Queued when a user has submitted the job, but it is waiting for a previous Restore execution to complete.                       |
| Running    | The Restore job is currently running. There can only ever be one running Restore execution at a time.                                            |
| Completed  | The Restore has completed with zero errors reported back.                                                                                        |
| Aborted    | The Restore has been aborted by a user.                                                                                                          |
| Error      | The Restore has completed but some (or all) of the records were unable to be restored due to an error.                                           |

## Creating a New Restore Job

The Restore process starts with the creation of a new Restore job. From the Restore page, click the `New Restore` button. This launches a small guided process that takes you through the steps to create and launch either a **Point in Time Restore** job or a **Create Records Restore** job.

### Select a Data Source

#### **Search**

You can use Global Search to find records to be restored; simply select the object and record status, set the date filter and use the optional field filters to narrow down your search. The search will start by returning 10 parent records, but the remaining results can then be restored via a Batch Restore execution.

#### **CSV**

Upload a CSV file to restore records by record id. This will restore records in a batch of up to 10,000, but a Batch Restore execution can be setup to restore the remaining records on the file. Please note that the CSV must contain a header named `Id` and must not exceed 500 MB.

#### **Report**

You can use a report in Salesforce to indicate the records that need to be restored. To select the records that are going to be restored, create a report in Salesforce that

* is for a single object only
* contains (at least) the record ID as a column
* doesn't have any cross object joins, grouping or summary information
* is stored in a folder that the GRAX Integration User has access to

{% hint style="info" %}
**GRAX Reports**

For the report to be visible in the GRAX Application it must be saved to a folder with the name GRAX in it, or to have the name GRAX in the Report Title. The report also needs to be saved to a location that the GRAX Integration User has access to. We recommend that you create a specific folder, "GRAX Reports" that you use to keep GRAX specific Salesforce reports in.
{% endhint %}

{% hint style="info" %}
**100k Record Limit using Reports**

If you seed using the Salesforce Report, there is a limit of 100,000 records that can be loaded into the GRAX Application. If GRAX identifies there are more than 100,000 records in the report, you won't be able to proceed. GRAX first takes a few seconds to analyze the Salesforce report to make sure there aren't more than 100,000 records. If there are too many records, the report needs to be reduced in size before continuing.
{% endhint %}

#### **Record IDs**

You can manually enter up to 200 record ids to restore by listing them and separating each one by either a comma or a new line.

### Select Restore Options for Point in Time Restore

GRAX Point in Time Restore allows the user to be specific about which data they wish to restore, allowing a partial update of a record to a new version. Point in Time restore will restore records that are currently live in Salesforce to their state at the specified date and time, while skipping archived or deleted records.

This can be particularly useful when a process has been incorrectly updating data, while at the same time users have been working with these records.

#### **Select the Point in Time and Choose Restore Fields**

The Point in Time looks at the date fields on the record and selects the values from the GRAX Data Vault that were the latest version at the date / time specified by the Point in Time. Depending on the object type, this would be the `System Modstamp`, `Last Modified Date` or `Created Date` standard fields.

<figure><img src="/files/xEsxNlIHixS9Td2HRoQC" alt=""><figcaption></figcaption></figure>

Within Field Selection, fields need to be added to the Restore by selecting and moving the fields within the filtered dueling picklist control. To restore all fields, select all fields by moving them into the right hand list.

<figure><img src="/files/lZA7ceoGuPXu6lVWNq5J" alt=""><figcaption></figcaption></figure>

{% hint style="info" %}
**Records Filtered by Point in Time**

It's possible to filter your initial Restore seed by selecting a Point in Time that is before the created date of the records you wish to restore.

\
If the Restore confirmation record count doesn't match the expected record count from your Restore seed, it may be that you have excluded some of these records by the selection of this Point in Time value.
{% endhint %}

### Select Restore Options for Create Records Restore

The configuration page for the Create Records restore allows you to select the level of child records to restore and provides an option to skip specified objects. There are also options to send emails regarding the job and disable automation, which can sometimes help when testing; required parent records are always included.

<figure><img src="/files/n25bFQ1utzA4FtBM2GGn" alt=""><figcaption></figcaption></figure>

### Preview Restore

Once the Restore configuration has been set, GRAX begins to prepare the data set for restore from the GRAX Data Vault. This process can take some time (minutes even) depending on the size of the Restore and while this evaluation is underway you won't be able to proceed from this step.

{% hint style="info" %}
**Execution in Pending State**

If you close the tab here, you can return to the job by clicking on the newly created Restore execution in the Restore home tab which will show in the "pending" state; there will also be a banner on this page for each pending job.

Cancelling a Restore execution deletes it from the list on Restore home.
{% endhint %}

Here you are presented with a preview of the records and values that are going to be restored. This data is different from the Restore seed - it's the data that is going to be written back to your Salesforce org as part of the Restore execution, so it's worthwhile ensuring that you are comfortable with your selections.

Once the data finishes the preparation phase, the `Next` button activates. You can download the complete record set as a CSV file here as well.

#### **Null or Empty Values**

There are a number of scenarios that could mean your GRAX Vault contains records but not values for all fields that you are trying to restore.

* The field might have been empty at the time of the backup
* The field might not have existed at the time of the backup
* The field might not have been accessible to the GRAX Integration User at the time of the backup.

Null values appear in the Restore preview as #N/A and reset any field values in the record being restored to empty. If this isn't the intended behaviour, deselect this field before continuing.

#### Overrides and Relationships

When viewing a preview of the Restore job, you can change to a list view to provide options for overrides and selecting/deselecting relationships. To override a field value for a Restore job, select the object on the left hand side, click on the `Overrides` section, and then select the field you want to proceed with. You can enter a new value to be written to this field, or you can leave the value blank to exclude this field from the restored record.

<figure><img src="/files/tBeEBPUZjonqoVI1SJtJ" alt=""><figcaption><p>Restore Overrides</p></figcaption></figure>

You can also navigate to the `Relationships` section to include or exclude specific relationship attributes for the restored records.

### Launch Restore

The Point in Time Restore confirmation screen informs the actual number of records that are going to be affected, the fields on those records and the point in time to which that data is going to be restored.

<figure><img src="/files/dO2iPon9GlAHFMezkUVR" alt=""><figcaption><p>Restore Warning Popup</p></figcaption></figure>

If this all looks good, clicking the `Restore Data` button starts the process. Please note that for Create Records Restore jobs, this notification will not appear, but a graph that shows the records to be restored will be available for review before launching the restore.

{% hint style="info" %}
**Restoring Data is Writing to Salesforce**

This writes data to your configured Salesforce environment; be certain you understand the possible ramifications this might have.

Please review the [Restore Best Practices](/protect-data/restore/restore-best-practices) as these apply to both Point in Time and Create Records Restore jobs.
{% endhint %}

## Monitoring a Restore Execution

Once the Restore execution has been submitted it can be monitored in the GRAX Console. This submits records in batches to Salesforce so you can see a number of different outcomes here.

<figure><img src="/files/SFI4wxqqAN9ZYG56KHmm" alt=""><figcaption><p>Restore Job Progress/Status Details in Progress</p></figcaption></figure>

{% hint style="info" %}
**Aborting a Restore**

You can abort a Restore Execution but this won't perform a Rollback of data that has been successfully processed as part of this Point in Time Restore. Any data that has been successfully updated would need to be included in a new Point in Time Restore if it needed to be reverted to a previous state.
{% endhint %}

### Restore Records Status

In addition to the status of the job as a whole, individual batches of records have a status while the job is running and once it has completed.

| Status     | Description                                                                            |
| ---------- | -------------------------------------------------------------------------------------- |
| Pending    | Data has been prepared but not yet submitted to Salesforce                             |
| Submitted  | Data has been submitted to Salesforce, waiting on the result from this API transaction |
| Successful | Data was successfully restored.                                                        |
| Error      | Data failed to be restored.                                                            |

## Restore Errors and the Retry Flow

When restoring records to Salesforce you may encounter errors like validation rule failures, changes to the object schema, or other users updating the same records.

GRAX Restore allows a user to retry just the failed records. This creates a new Restore execution with this subset of data as the restore seed.

<figure><img src="/files/pwP8Z9Opy2TxRmSNJCel" alt=""><figcaption><p>Restore Job Progress/Status Details with Error</p></figcaption></figure>

Here is a Restore that has failed due to an inactive user as the value in the Owner field. This can be fixed by retrying the restore job, and setting an override with a null value to the Owner field.

Restore errors should provide the needed information to resolve the issue; typically a change to validation rules or triggers, or a field override is necessary to proceed.


# Restore Best Practices

Restoring data via GRAX is incredibly easy to do with a few clicks, but your Salesforce administrator and team needs to prepare the environment and ensure all considerations are taken into account. Unlike backing up data, restore involves modifying data in your Salesforce org (inserts/updates) which can have unintended consequences if the necessary preparation and validation isn't done. GRAX simply leverages standard Salesforce inserts and updates, but depending on the way your schema is constructed, there are several rules and cascading impacts that can affect your data. This article gives an idea of what to expect and best practices we have seen with customers that are successful with restoring across large amounts of data and with complex logic.

## General Restore Considerations

Let's take a look at some of the more common scenarios that you should test and validate to prep any environment where you plan to be restoring data:

| Scenario                    | Details                                                                                                                                                                                                                                                                                                                                                                                                                                                   |
| --------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Triggers                    | Ensure you have validated all custom Apex code/triggers present on any objects that you plan on restoring. You need to determine how you want to handle these scenarios. For example, triggers could be preventing inserts of certain records, or kicking off updates across other related records etc.                                                                                                                                                   |
| Validation Rules            | One of the most common scenarios is restoring a record that may have met all validations previously, but no longer meets and is blocked from insert/update                                                                                                                                                                                                                                                                                                |
| Permissions                 | Ensure any user who is restoring data has the correct permissions to do so. If a user tries to restore a custom object for which they have no access to create via their Salesforce permissions, this won't be allowed. Or if a user tries to restore and set a record type which they don't have access to, for example. Outlining your business use cases for restore and ensuring proper compliance with existing Salesforce architecture is critical. |
| Workflow / Process Builders | Understand implications of restoring data and firing relevant rules and automation                                                                                                                                                                                                                                                                                                                                                                        |
| Lookup Filters              | Another common area where restores are blocked due to restored records not matching required lookup filter criteria. Easiest way to avoid this is to make lookup filters optional.                                                                                                                                                                                                                                                                        |
| Restricted Picklist Values  | Review picklist fields that might be set as `restricted` and thus block incoming values via a restore                                                                                                                                                                                                                                                                                                                                                     |
| Required Fields             | Any changes to required fields could cause issues if incoming restored data doesn't meet criteria                                                                                                                                                                                                                                                                                                                                                         |
| Duplicate / Matching Rules  | Incoming restored records may be blocked by duplicate rules set up, which may be intended and desired behavior depending on use case.                                                                                                                                                                                                                                                                                                                     |
| Set Inactive Owners         | As described in the GRAX Restore options article, be sure this user permission is enabled for the restoring user if you are trying to restore records and set inactive users as record owners.                                                                                                                                                                                                                                                            |
| Record Type Creation Access | Each object may be associated with one or more record types. Access to each record type must be granted on an individual object basis within the GRAX Integration User permission set in order to enable restore jobs for these objects.                                                                                                                                                                                                                  |

## Example Object Considerations

Salesforce has various behind-the-scenes restrictions and rules on many standard objects. Please be sure your administrator/SI has verified restore of all scenarios and relevant objects in your sandbox, as very often this could uncover a Salesforce standard rule and/or a custom rule put in place that blocks the restore. The GRAX tool has features such as custom mappings that can aid in getting the data restored successfully, but you need to have resources who understand your specific environment to validate the use cases.

<table data-view="cards"><thead><tr><th></th><th></th></tr></thead><tbody><tr><td><h4>Documents</h4></td><td><ul><li>You may want to first restore Document folders before restoring Documents so they get associated to proper folder</li></ul></td></tr><tr><td><h4>Leads</h4></td><td><ul><li>Validate use case of restoring converted leads as Salesforce has various fields behind the scenes and standard behavior</li></ul></td></tr><tr><td><h4>Account Team Member</h4></td><td><ul><li>Salesforce only allows creation of AccountTeamMember records that are active users</li></ul></td></tr><tr><td><h4>Email Message</h4></td><td><ul><li>ValidatedFromAddress is a restricted "behind the scenes" populated from org wide addresses.</li><li>Can use GRAX restore mapping to map ValidatedFromAddress to an org wide address if needed</li><li>ValidedFromAddress must match FromAddress</li><li>With enhanced email enabled, Salesforce auto-generated a task record "behind the scenes" upon creation of EmailMessage record. If you restore a task first, and then later restore the EmailMessage record, Salesforce would auto-create another task and there may appear to be duplicates in related lists. We recommend validating and restoring only EmailMessage record and accounting for Salesforce's auto-creation of task.</li><li>May also get insufficient access rights errors on certain private emails that don't have RelatedToID if you don't have access</li></ul></td></tr><tr><td><h4>Content</h4></td><td><ul><li>Salesforce Content-related objects also work in unique ways, with multiple standard objects interacting and being auto-created by Salesforce in various ways</li><li>When restoring content, select ContentVersion as the main object and ensure you are toggling option to restore children, as this restores ContentDocument, ContentVersion, and ContentDocumentLink</li><li>ContentDocument and ContentVersion objects will always show the GRAX Integration User as the owner of the restored record instead of the original owner, due to access restrictions with private user libraries</li></ul></td></tr><tr><td><h4>Contracts</h4></td><td><ul><li>Salesforce dictates that when inserting contracts they must have a status of <code>Draft</code></li><li>So to restore, you may need to use custom mapping. You could create a custom field in the destination that houses the true contract status</li><li>Map contract standard <code>Status</code> field to the new custom field (let's call it Original Contract Status)</li><li>Default the standard <code>Status</code> field to <code>Draft</code>.</li><li>After restoring everything you need to use Data Loader to do an update and set the standard Status field back to it's true status using the value that was stored in the custom <code>Original Contract Status</code></li><li>Also, once a contract has an <code>activated</code> status category, you can edit every field EXCEPT you cannot change the status back to Draft or you can't change the Account</li></ul></td></tr></tbody></table>

## Third-Party Managed Packages

{% hint style="danger" %}
**Third Parties Not Supported**

GRAX doesn't support restoring data for third party package customizations/objects such as FinancialForce, Veeva etc. You do so at your own risk, given the various customization these third party packages can include that may prevent and have unintended consequences on DML operations.
{% endhint %}

As you saw with Archive, you'll need to account for potential customizations when restoring data. There can often be triggers and managed package code either preventing inserts or validating data upon insert. Test the use case in a sandbox to understand and work with your SME on workarounds. For example, "veevatized" environments (Veeva CRM) have special considerations about inserting data. GRAX Restore leverages a basic insert so you need to understand those implications for the specific objects you choose to restore.

## Exceptions to Allow Restore

As mentioned in the general considerations above, the GRAX restore runs as the integration user, so the integration user's permissions/profiles apply. So just like any other record creation in Salesforce, this user needs the correct permissions. If there are validations/triggers, for example, blocking the insert of a new record, you can either address the root cause (bad data, for instance), or you can create exceptions within the triggers/validation rules to allow for records to be restored. There are a few of ways to do this, including but not limited to:

1. Specify a set of users that should be exempt from said validations, triggers etc.
2. For some customers, not all users should be able to restore data. Often there are change management procedures put in place that funnel restore requests to a single point of contact. If this is the case, you can use the designated 'integration' user for all restores and thus more easily exempt this user from relevant triggers and validations.
3. Use the GRAX Restore Mapping feature to set a default value for a custom field on each object that you would like to be exempt. Since GRAX then updates this 'flag' field upon restore, you can use this field for exemptions within the validation rule, for instance.

## Change Management

As a best practice, many Salesforce customers implement an internal change management process to ensure any configuration changes are sent through the proper approval flow, tested, and deployed. it's important to ensure GRAX is integrated into your existing change management process. For example, submitting a request for a new validation rule on the Case object could impact users who typically restore cases via GRAX. This should go through a layer of additional validation based on objects that are involved in GRAX processes.

Customers also often implements an approval process for restores where there is one superuser designated for restoring records and other users must submit request for restore with reasoning. Oftentimes, business users think they need to restore data but really they just need to view certain information about the archived record. We always recommend first seeing if the restore use case can be solved with [Global Search](/reuse-data/global-search) and visualization options, before confirming if you actually do want to insert new records into your environment.

## Other Considerations

### Restoring Archived Records

When you restore an archived record, this creates a brand new record (with a new Salesforce ID). Salesforce doesn't have a 'restore' function, GRAX uses the 'create' call, so this makes a new ID.

### Read-Only Records

There are certain objects that are "read-only" within Salesforce, such as `Report`. These objects are unsupported for restores due to this and can not be written via a restore job.

### Audit Fields

If you would like certain audit fields restored, please ensure you have the correct permissions set up to open these fields up, and review all [Salesforce Considerations](https://help.salesforce.com/articleView?id=000331038\&type=1\&mode=1) for audit fields. For instance, these can only get set upon record creation.

### Mass Restore

When selecting and restoring multiple records at a time, GRAX restores the most recent version of the record

### Validation Recommendations

Always conduct initial validation in a development environment, and then follow that up by validating fully in a staging/full sandbox. Expect to run into a few of the 'gotchas' outlined in this article. While GRAX facilitates the restore process, each org is different and you must rely on your administrator and/or SI to conduct the proper testing and validation.

In larger, more complex Salesforce environments, GRAX recommends setting up policies and procedures specifically for the restore process. Given that the restore process is essentially equivalent to inserting records (potentially multiple records and relationships) a careful analysis of potential impacts is necessary. This article provides several considerations to work into your validation and go live process, but in general we have found that following these high level steps result in successful deployments of GRAX:

| Step                                 | Comments                                                                                                                                                                                                                                                                                                                                                                                                                                                             |
| ------------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Initial Restore Criteria             | Obtain criteria for each object you plan on restoring. Do you also want to restore children with the parent?                                                                                                                                                                                                                                                                                                                                                         |
| Technical Checklist                  | For each restore use case/criteria, have someone familiar with all customizations within the environment go through each object that may be restored. Use the 'gotchas' in this article as a starting point for listing out configurations in your environment that may block or interfere with inserts/restores                                                                                                                                                     |
| Business Checklist                   | For each restore use case/criteria, have someone familiar with all customizations within the environment's business process go through objects and provide feedback on how business process could be affected if certain objects (and their relationships to other objects) are recreated or inserted again. For example, would this fire off an undesired workflow email alert?                                                                                     |
| Review Checklists with GRAX Sponsors | Before running any restores even in sandboxes, ensure the initial technical and business checklists are reviewed with the GRAX sponsors as this exercise helps various teams be on the same page regarding a specific org's restore needs. Very often we find that a use case for restore is really just a use case for visualizing the archive data rather than an actual need to recreate the data back into Salesforce and impact Salesforce data storage limits. |
| Archive Relevant Records             | To set up the restore of records, first archive some small datasets so that you can subsequently restore/recreate                                                                                                                                                                                                                                                                                                                                                    |
| Test Restore Use Cases               | Now use the GRAX restore to test out various use cases                                                                                                                                                                                                                                                                                                                                                                                                               |
| Confirm Restores                     | The GRAX restore process is asynchronous so after clicking restore on one or more records, you should to navigate to the Logs tab and view restore logs to see which records were created or may have failed due to a validation rule for example. Also be sure to do click-testing to ensure the records were created successfully and were not impacted by any other business processes.                                                                           |
| Address Findings                     | Once you have conducted enough testing, you should have a list of findings. For instance you could have a handful of validation rules and triggers that you need to address. Depending on the individual restore use case for specific objects, you may want to create exceptions (described more in this article)                                                                                                                                                   |
| Final Validations                    | If you do edit any existing metadata, be sure to re-test the restore use cases before going to Production                                                                                                                                                                                                                                                                                                                                                            |
| Ongoing Change Management            | Even after you are restoring records in Production, we recommend putting a process in place within the change management practices within your company. For instance, if new triggers/validations are built, they should be analyzed with respect to potential impacts on existing restore use cases, before deployments.                                                                                                                                            |


# Purge

{% hint style="danger" %}
**Do Not Modify Data Directly**

The GRAX data storage layer is a proprietary, compressed, bit-level data store that isn't human readable or editable. Never modify the dataset in storage yourself, including the deletion, modification, renaming, or moving of storage objects. All interaction with the stored data should occur via the GRAX Application.
{% endhint %}

## What Is Purge?

Purge is the new Data Lifecycle Management feature offered by GRAX that supersedes Delete Forever. Purge allows you to define data retention rules that manage the permanent deletion of data from the GRAX Data Vault. This feature is included with GRAX Enterprise and Data Archive and Lifecycle Management licenses.

*Please note that the Purge feature is **not** intended for storage cleanup or reducing storage capacity (Archive is the functionality to be used for those purposes); it is designed to permanently delete data for privacy, legal, and/or compliance reasons and should be used with caution, as data can not be recovered after it has been purged.*

## How to access Purge

Purge is integrated in two places within the GRAX Application.

#### Purge Menu Page

Click on Purge in the menu and you will see the button New Purge. This takes you into the Purge workflow.

<figure><img src="/files/U59sMfL2APJWGgT3AnB9" alt=""><figcaption><p>Creating a New Purge via the Purge Page</p></figcaption></figure>

#### Record Details

A second method of selecting records to purge can be accessed through record details. Either click on any record link or enter the ID in the Lookup By ID box in the header to arrive at the record details view. Clicking on the vertical ellipsis in the header gives you the option to purge.

<figure><img src="/files/gd8tE9amnblUVfEhDwKY" alt=""><figcaption><p>Creating a New Purge via the Record Details Page</p></figcaption></figure>

## Purge Workflow

To purge data, the records must first be deleted in Salesforce or Archived by GRAX. Purged records will be permanently removed from the GRAX Data Vault and will no longer be available to review or restore. Purge provides a workflow to guide you through the steps to purge data.

{% stepper %}
{% step %}

### Select the records you want to purge

There are a few ways to tell Purge what records you want to include:

{% tabs %}
{% tab title="Search for Records" %}
If you're purging records based on specific criteria — such as "All Cases related to a contact with the last name 'Smith'" — you can use Search to quickly find all such records:

<figure><img src="/files/6gAmhx1vZTULG61xTsQH" alt=""><figcaption><p>Using Search to Determine Purged Records</p></figcaption></figure>
{% endtab %}

{% tab title="List of Record IDs" %}
If you're purging a fixed set of known records, you can purge them simply by entering one record ID per line:

<figure><img src="/files/RmjUvUZE205Ui5Vc5AZG" alt=""><figcaption><p>Providing Record IDs to Purge</p></figcaption></figure>
{% endtab %}

{% tab title="Upload a CSV" %}
If you have assembled or determined the list of records to purge from an external system or tool, you can use a CSV as the input source:

<figure><img src="/files/Je71Xc2LO3eAnL66imx7" alt=""><figcaption><p>Providing a CSV of Records to Purge</p></figcaption></figure>
{% endtab %}
{% endtabs %}
{% endstep %}

{% step %}

### Choose Purge options

We provide options to verify the records in Salesforce and/or receive an email of important changes.

<figure><img src="/files/MhCNIH06c4RPjp2ZY9DH" alt=""><figcaption><p>Optional Behaviors of Purge</p></figcaption></figure>
{% endstep %}

{% step %}

### Preparing the Hierarchy

GRAX builds and graphs the hierarchy of your records to prepare for purge. You can see the graph of your records and the number of records that will be purged.

<figure><img src="/files/vdlrck1LSrb93KzwhzKO" alt=""><figcaption><p>Pending Purge Hierarchy Details Graph</p></figcaption></figure>

There is also a list view where you are presented with tools to configure a purge allowing you to skip records or include additional objects referenced by your purge data.

<figure><img src="/files/EE24pqKNJ7WubFnZTJz8" alt=""><figcaption><p>Pending Purge Hierarchy Details List</p></figcaption></figure>

You may not want all objects that are referenced in the graph hierarchy. You have the option to skip objects that you don't wish to include. You can define additional referenced objects to include via the Relationships tab.
{% endstep %}

{% step %}

### Execute the Purge

After clicking Purge, you are prompted to confirm.

<figure><img src="/files/TPxcjucJrMn81sBVilfm" alt=""><figcaption><p>Execute Purge Confirmation</p></figcaption></figure>

You will be presented with a progress indicator as the data is purged. Once complete, you will be presented with a summary of the purge. You can see the number of records purged, the number of records skipped, and the number of records that failed to purge. You can also see the number of records that were purged from each object.

<figure><img src="/files/whZN5tIXxTJdwSTqEVGt" alt=""><figcaption><p>Successful Purge Details Graph</p></figcaption></figure>
{% endstep %}
{% endstepper %}

## Auto Purge

After completion of a purge job created from a search source, you can choose to set up an auto purge.

<figure><img src="/files/2uDZr7XrytpJD1re9JWy" alt=""><figcaption><p>Creating an Auto Purge</p></figcaption></figure>

This takes you to the Auto Purge Detail page. You can rename the purge job, skip new objects, and enable it to run as an Auto Purge. You can also choose to receive an email notification when each purge batch is complete or if the job encounters an error.

<figure><img src="/files/tABvng3wr04cYbWCNft0" alt=""><figcaption><p>Configuring an Auto Purge</p></figcaption></figure>

## Purge Jobs

Prior Purge jobs are shown in the Purge tab of the menu with detailed information on each. You can see the status of the job, the number of records purged, the date the job was created, the duration of the job, and the success rate. Clicking on the job name takes you to the job details page where you can see the records that were purged.

<figure><img src="/files/qs2JCYn83hBrK0XK2ubr" alt=""><figcaption><p>Purges List</p></figcaption></figure>

Currently enabled and paused Auto Purge jobs are displayed on the top of this page with details on when the job was last modified, the number of records purged, the date the job was last ran, and the next scheduled run. Clicking on the job name takes you to the job details page where you can see the records that were purged. You can pause all Auto Purge jobs by clicking the `Pause Auto Purges` button. You can also view disabled Auto Purge jobs by clicking the `View Disabled` option on this page.

## Purging Live Records

You can purge records that are still live in Salesforce if you want to remove the data completely from GRAX. This action will only remove the record from GRAX and does not touch the record within Salesforce. If you do not want the data to be backed up again subsequently, you will need to anonymize the data in Salesforce (which will result in anonymized data being backed up), remove access to the object/record which will prevent backup completely, or delete it from Salesforce directly.

To enable the ability to purge live records, you will need to navigate to the `Settings` page of the GRAX Application, expand the `Advanced Features` section, and toggle on the related option.

## Global Search for Purged Records

Global Search now allows you to search for records that have been Purged (permanently deleted). To search for Purged records, select any Status other than "Live" and add a date filter configured with "Order By: Purged At" and select an appropriate time frame. The Purged records returned by Global Search will not contain any field data other than RecordID. The CSV download of Global Search results will now contain a `purgedAt` date column.

## Frequently Asked Questions

#### When purging file-related records such as Attachment and ContentVersion, will associated files be deleted?

Yes, purging file-related records will also delete the associated files.

#### Will purging data remove the associated parquet files written to the Data Lake?

No, we do not modify parquet data after it has been written.

#### Will purging data remove records that have been seeded to another org?

No, purging will not affect any records that have been seeded.

#### Will purging data remove records from Delete Tracking?

Delete tracking will still point to a purged record, but there will be no data shown, just a reference to it being purged.


# Reusing Your Data

## Turn Your Salesforce Backup into a Strategic Data Asset

GRAX doesn't just protect your Salesforce data—it transforms it into a queryable, analyzable data product that powers modern analytics, AI, and business intelligence across your organization.

## Why Reuse Your Salesforce Data?

### Complete Historical Context

GRAX captures comprehensive Salesforce data history from day one of your backup—including field changes, deletions, and record evolution that Salesforce's native tools don't preserve. Unlike Salesforce's 90-day field history tracking or limited Data Cloud retention, GRAX gives you:

* **Years of historical depth**: Track trends across quarters and years, not just days
* **Deleted record access**: Query records removed from Salesforce production
* **Point-in-time analysis**: See what your data looked like on any historical date
* **Complete audit trails**: Field-level change history for compliance and investigation
* **Training datasets**: Rich historical data for AI/ML model development

### Data You Actually Own

Your data lives in **your cloud storage** (AWS S3, Azure Blob, or GCP Cloud Storage), not locked in a vendor platform. This means:

* **No API limits**: Query as much as you need without throttling
* **No per-query costs**: Beyond standard cloud storage fees
* **Your tools, your choice**: Use any analytics platform, warehouse, or BI tool
* **Data sovereignty**: Full control over data residency and governance
* **Cloud-agnostic**: Works with AWS, Azure, or GCP

### Enterprise-Proven Scale

Fortune 100 companies trust GRAX to handle their mission-critical Salesforce data at massive scale—processing hundreds of millions of record versions per week in production environments. Whether you're analyzing millions of records or building real-time dashboards, GRAX handles enterprise-scale workloads with sub-2-hour latency for operational analytics.

## How GRAX Fits Your Data Architecture

**GRAX provides the Bronze layer.** Your complete Salesforce history as Parquet files in your cloud storage (S3, Azure Blob, GCS). From there, customers take different approaches:

### Direct Query (Serverless)

Query Bronze directly with minimal transformation. Cost-effective for analytics workloads.

* **AWS:** Athena, Glue external tables
* **GCP:** BigQuery external tables
* **Azure:** Synapse serverless pools
* **Local/Open Source:** DuckDB for cost-free analytics on your laptop or server

### Data Lakehouse Platform

Unified analytics and data engineering on Bronze.

* Databricks (medallion architecture)
* Azure Synapse Analytics
* AWS EMR + Spark

### Traditional Warehouse

Transform and load into a data warehouse for BI.

* **Transform:** dbt, Airflow, Cloud Dataflow, custom SQL
* **Warehouse:** Snowflake, Redshift, BigQuery
* **BI:** Tableau, Looker, Power BI, QuickSight

Many customers use combinations of these approaches—for example, running Athena for ad-hoc queries while maintaining Snowflake for production dashboards.

**The key:** GRAX doesn't lock you into any approach. The open Parquet format means you can start simple and evolve as needs change.

## Choose Your Path

The right integration approach depends on your team's capabilities and goals:

| If you want to...                                                                                                     | Start here:                                                                            | Best for                                                         |
| --------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------- | ---------------------------------------------------------------- |
| <p><strong>Query historical data with SQL</strong><br>Build BI dashboards, run analytics, or feed data warehouses</p> | <p><strong>Data Lake</strong><br>Automatic Parquet export to your cloud storage</p>    | <p>Data analysts<br>BI teams<br>Data engineers</p>               |
| <p><strong>Find and investigate records</strong><br>Search historical data, explore relationships, audit changes</p>  | <p><strong>Global Search</strong><br>Full-text search across all GRAX data</p>         | <p>Salesforce admins<br>Support teams<br>Compliance officers</p> |
| <p><strong>Recover deleted data</strong><br>Restore records with full relationships back to Salesforce</p>            | <p><strong>Global Search</strong><br>Find, Review, Restore workflow</p>                | <p>Admins<br>Data recovery teams<br>Support staff</p>            |
| <p><strong>Seed developer sandboxes</strong><br>Copy production data (anonymized) into dev/test environments</p>      | <p><strong>Sandbox Seeding</strong><br>On-demand data copying with anonymization</p>   | <p>Developers<br>QA teams<br>Training admins</p>                 |
| <p><strong>Build custom integrations</strong><br>Automate workflows or integrate with internal tools</p>              | <p><strong>Public API</strong><br>OpenAPI REST interface for programmatic access</p>   | <p>Developers<br>Integration engineers<br>Automation teams</p>   |
| <p><strong>Access GRAX from Salesforce UI</strong><br>View history, search, or restore without leaving SFDC</p>       | <p><strong>Managed Package</strong><br>Lightning components embedded in Salesforce</p> | <p>End users<br>Salesforce admins<br>Support agents</p>          |

## Core Capabilities

### Data Lake: SQL Analytics Foundation

**Automatically exports backup data to Parquet format** for high-performance analytics.

**What you get:**

* Cloud-native Parquet files in your S3/Azure/GCP storage
* Historical depth with all record versions over time
* Works with AWS Athena, Azure Synapse, Databricks, Snowflake, BigQuery
* Sub-2-hour latency for operational analytics
* Continuous incremental updates (no batch dumps)

**Perfect for:**

* BI dashboards without Salesforce API limits
* Data warehouse loading (Snowflake, Databricks, Redshift)
* Historical trend analysis and forecasting
* Machine learning training datasets
* Cross-system analytics (join with ERP, marketing, etc.)

**Architecture fit:** Your Bronze layer for downstream transformations

[Get started with Data Lake →](/reuse-data/data-lake)

***

### Global Search: Find Anything, Anytime

**Full-text search and investigation** across all GRAX historical data.

**What you get:**

* Search by any field value, date range, or text content
* View complete record history and change timeline
* Relationship graph visualization
* Export results or restore to Salesforce
* Template-based searches for common patterns

**Perfect for:**

* Finding deleted records for recovery
* Investigating data quality issues
* Compliance audits and field-level change tracking
* Training users on historical scenarios
* Root cause analysis of data problems

**Architecture fit:** Interactive investigation and recovery tool

[Explore Global Search →](/reuse-data/global-search)

***

### Sandbox Seeding: Production Data for Development

**Copy production data into sandboxes** with relationship preservation and optional anonymization.

**What you get:**

* Select records via Salesforce reports, SOQL, CSV, or Global Search
* Automatic relationship graph building (parent/child records)
* Deterministic or random data anonymization
* Full control over object inclusion and field overrides
* Faster than Salesforce's sandbox refresh cycle

**Perfect for:**

* Giving developers realistic test data
* QA testing against production scenarios
* Training environments with anonymized data
* On-demand sandbox refreshes (not quarterly waits)
* Testing complex integrations with real data shapes

**Architecture fit:** Development enablement and testing

[Start Sandbox Seeding →](/reuse-data/sandbox-seeding)

***

### Public API: Programmatic Access

**OpenAPI-based REST interface** for custom integrations and automation.

**What you get:**

* RESTful endpoints for search, backup, restore, and metadata operations
* Full OpenAPI specification at `/api/spec/grax.json`
* Token-based authentication with scoped permissions
* Webhook support for event-driven workflows (where available)
* Rate limits appropriate for enterprise workloads

**Perfect for:**

* Building custom applications on GRAX data
* Automating compliance and governance workflows
* Real-time data sync to operational systems
* Integration with internal tools and platforms
* Scheduled reporting and alerting

**Architecture fit:** Programmatic integration layer

[Explore the API →](/reuse-data/public-api)

***

### Managed Package: In-Salesforce Access

**Lightning components** that embed GRAX functionality directly in Salesforce UI.

**What you get:**

* Search component for finding historical records
* Record detail components showing change history
* Restore wizards integrated into page layouts
* Template-based search for common patterns
* Auto-updates via managed package releases

**Perfect for:**

* End users who never leave Salesforce
* Support teams needing quick record recovery
* Admins managing user access to GRAX features
* Zero-training adoption (familiar Salesforce UI)
* Governance via Salesforce permission sets

**Architecture fit:** User-facing access layer

[Install Managed Package →](/reuse-data/managed-package)


# Data Lake

Data Lake writes data from GRAX backups to your storage bucket in [Parquet](https://parquet.apache.org/) format. You can use the written data to build data warehouses, merge data with other systems, and more.

## Getting Started

### Enable Objects

To start, browse to Data Lake and enable your first objects by clicking `Add Objects`.

To help you get started, we’ve preselected the most common objects. You can customize these selections at any time, including removing any that were preselected:

* Account
* AccountContactRelation
* Campaign
* CampaignMember
* Case
* Contact
* Event
* Lead
* Opportunity
* OpportunityLineItem
* Task
* User

<figure><img src="/files/SKz0YUuRNKOAtg5HgpFz" alt=""><figcaption></figcaption></figure>

By default, all fields are written. If you’d like to write only specific fields, simply uncheck `Include all fields for new objects`. at the bottom of the `Configure` page.

If any objects were added without `Include all fields for new objects` selected, you will receive a configuration pop-up for each object, allowing you to [exclude](#excluding-fields) fields from that object. Skipping the configuration pop-up for an object will add the object with all fields in a paused state, allowing you to revisit the configuration later.

### Excluding Fields

To exclude fields from an object, deselect `Include all fields for new objects` when adding it, as described above.

To exclude fields from an object already added to Data Lake:

1. Pause writing for the object you wish to configure by clicking pause in the `Actions` column.
2. Click the gear symbol in the `Actions` column to open object configuration.
3. Select the fields to exclude from this object and click `Update`.

<figure><img src="/files/oPtRTcrPwNisKWqjX5Ov" alt=""><figcaption></figcaption></figure>

{% hint style="warning" %}
Excluding fields from an object does not remove data that has already been written to the Data Lake. The excluded fields will only be omitted from future writes. To rewrite the object’s history without those fields, remove the object and then re-add it with the fields excluded.
{% endhint %}

### Object Status

After you enable an object it will take some time to populate the data lake. You will see the status go from `Backfilling` with a percentage to `Current` when it is complete. The initial backfill may take a while as it writes out data for every version of every object in your backup history.

#### Object Actions

You can pause and resume individual objects in the object actions column.

Once an object is paused, there are several actions available:

* Clicking <img src="/files/i6lOnjWvqeutbOoncNGy" alt="" data-size="line">will delete the object configuration. This does **not** remove any data already written to Data Lake. Parquet files already written can be manually removed if desired.
* Clicking <img src="/files/4pY1KxIlQZ10RBOWx50a" alt="" data-size="line">opens the object configuration screen, allowing you to [exclude fields](#excluding-fields) from the object.

## Write Format

### Paths

When Data Lake is enabled for an object, it begins writing all data in GRAX backups for that object. Data Lake writes files to your storage bucket with paths that look like:

```
parquet/v2/org=X/object=Account/batch=05e0be100/data-16f5e66e800.parquet
parquet/v2/org=X/object=Account/batch=05e0be100/data-16f5f42a201.parquet
parquet/v2/org=X/object=Account/batch=05e0c89c0/data-16f61d5d004.parquet
```

The `batch=05e0c89c0` portion of the path is to group files into separate prefixes to [optimize performance in S3 and other object stores](https://docs.aws.amazon.com/AmazonS3/latest/userguide/optimizing-performance.html). It will increase as more data is written. For example, `batch=444444444` will not be used after `batch=555555555`. The `batch` value is not related to the data contained in the files, it is only for grouping files.

The `16f5e66e800` portion of `data-16f5e66e800.parquet` is to ensure unique and increasing filenames. It will increase with each file. For example, `data-44444444444.parquet` will not be written after `data-55555555555.parquet`. Similar to the `batch` value, it is not related to the data contained in the file.

### File Data

Each file contains a varying number of rows.

Rows are meant to reflect the full state of a record version (the combination of `Id` + `source__modified`) at the time of writing to Data Lake, not at the time of the relevant change. For example, record versions that are deleted before Data Lake is enabled will have `grax__deleted` set.

File sizes vary with data but are generally not above 150 MiB.

Within each `data-16f5e66e800.parquet` file, the data looks roughly like:

| Field                                               | Type                | Meaning                                                                                                                                                                  |
| --------------------------------------------------- | ------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `Id`                                                | string              | Salesforce Record ID.                                                                                                                                                    |
| `source__modified`                                  | timestamp           | The time the record version was modified in Salesforce (SystemModstamp).                                                                                                 |
| `grax__idseq`                                       | string              | A per-`Id` value that increases with record changes.                                                                                                                     |
| `grax__deleted`                                     | timestamp           | If the record has been deleted or archived, the time the record was deleted or archived.                                                                                 |
| `grax__deletesource`                                | string              | If the record has been deleted or archived, the source of the record delete. Will be `grax` for archives or `source` for Salesforce.                                     |
| `grax__purged`                                      | timestamp           | If the record has been purged, the time the record was purged.                                                                                                           |
| `grax__restoredfrom`                                | string              | If the record was restored from another record, the ID of the record this record was restored from.                                                                      |
| `<record field name>`, such as `Name`               | string              | Salesforce record field data, with the value from Salesforce (converted to a string).                                                                                    |
| `<record field name>_<type>`, such as `IsDeleted_b` | indicated by suffix | For non-string fields, one or more additional typed fields and values, `_b` for boolean, `_f` for float/integer, `_ts`, for timestamp, `_t` for time, and `_d` for date. |

Only `Id`, `source__modified`, and `grax__idseq` are guaranteed to be present.

A full example for an Account Parquet file might look like:

| `Id` | `source__modified` | `grax__idseq` | `grax__deleted` | `grax_deletesource` | `grax__purged` | `grax__restoredfrom` | `Name`    | `Fax`          |
| ---- | ------------------ | ------------- | --------------- | ------------------- | -------------- | -------------------- | --------- | -------------- |
| `1`  | `t4`               | `a`           |                 |                     |                |                      | `Alice`   |                |
| `2`  | `t5`               | `q`           |                 |                     | `t1`           |                      |           |                |
| `1`  | `t5`               | `b`           |                 |                     |                |                      | `Alicia`  |                |
| `3`  | `t1`               | `x`           | `t3`            | `grax`              |                |                      | `Bob`     | `800-555-1212` |
| `1`  | `t6`               | `c`           |                 |                     |                |                      | `Allison` |                |
| `4`  | `t8`               | `a`           |                 |                     |                | `3`                  | `Bob`     |                |
| `4`  | `t9`               | `g`           |                 |                     |                | `3`                  | `Bill`    | `888-111-5555` |

## Important Notes

**There will be duplicates.** To achieve low write time and increase safety, Data Lake can produce duplicate records.

* Use the combination of `Id` and `MAX(grax__idseq)` to determine the latest write for the latest version of a record.
* Use the combination of `Id`, `source__modified`, and `MAX(grax__idseq)` to determine the latest write per version of a record.

**Data can appear out of order.** Similarly for performance and reliability reasons, Data Lake can write data that may logically be out of order. For example, `data-X.parquet` may be written first with `Id=1`, `source__modified=t2` while `data-Y.parquet` may be written after with `Id=1` and `source__modified=t1`. This can also happen within the same `data-X.parquet` file.

* Use the fact that `grax__idseq` will increase for each `Id` and `source__modified` combination to order data.

**Each file can have a different schema.** The Parquet schema for each file is based on the data in that file. Only fields with non-empty values are considered and written.

**Files' schemas may include fields that contain no data.** It's also possible that a file's Parquet schema will include a field that has no data within the file.

**Typed fields may vary or clash over time.** As schema and data change over time, a typed field such as `Custom_Field__c_b` may stop receiving data if the schema and data indicate it changes to a string. Or `Custom_Field__c_d` may stop receiving data in favor of `Custom_Field__c_t` if schema and data change to indicate it changes from an date to a timestamp.

**Files written after a record has been purged will contain no field data for that record.**

## Frequently Asked Questions

#### How many objects should be enabled at the same time?

You should add all required objects to the `enabled objects` list; this ensures objects are pushed to Data Lake as efficiently as possible. GRAX continuously writes files for each object as capacity becomes available.

#### Why does the record count for an object in Data Lake not match the record count shown in Backup?

For backup, the numbers are split up into "records" and "versions." For Data Lake, the number of records and versions is combined in the “total records written” number. Please keep in mind that there might also be a small discrepancy between the totals if an object is still catching up in Data Lake. Additionally, if you had records backed up via Legacy Backup, those numbers are not included in the Backup totals but are shown in the Data Lake numbers.

#### How do I rewrite an object in Data Lake if new attributes have been added or field permissions have been updated?

You can remove an object from Data Lake configuration and then [add](#enable-objects) it back. This does not remove the previously written data from the parquet files, and duplicates any records that were already written and which are still present in the GRAX dataset.

{% hint style="info" %}
Before removing the object, review the object configuration to check if fields were [excluded](#excluding-fields), so you can exclude the same fields when adding the object back.
{% endhint %}

#### Should I continue to run Backup and Archive jobs while objects are being enabled for Data Lake?

Yes, GRAX is designed to have all these tasks run concurrently without diminished performance.

#### What factors impact the speed of Data Lake processing?

There are many variables to the speed including the amount and size of data, available CPU, other app activity, etc. There is no set time frame for how long writing an object (or objects) takes as this is determined by specific factors within each org.

#### How can I get Data Lake objects written faster?

Data Lake speed is dependent on various factors such as the size and quantity of objects. There is no action that can be taken to increase the writing speed, but GRAX is continuously working to maximize efficiency of this feature.

#### Is there any effect on the speed/performance in other areas of the app when running Data Lake?

Functionality that needs to scan backup data (Global Search, archive jobs, etc.) might run a bit slower than usual, but there should not be any noticeable difference or related errors.

#### What are the necessary CPU/VM resources needed to run Data Lake effectively?

Customers must have at least the minimum requirements for GRAX as defined [here](/infrastructure/requirements/technical-requirements). This allows Data Lake to run as intended, but having better CPU and RAM resources improves speed and capacity.

#### Can I turn Data Lake on and off if needed?

Yes, you can remove objects from the enabled list to pause Data Lake for a specific object. Once those objects are added back to the enabled list, Data Lake picks up where it left off. This might be useful if prioritizing certain objects or if internal flows need to be adjusted.


# AWS Data Lakehouse

GRAX Data Lake automatically organizes your CRM data as Parquet files in S3 for arbitrary on-demand analytics queries.

GRAX Data Lakehouse uses AWS Glue to catalog your data lake data, and AWS Athena to query it by SQL queries that run on the Athena in a serverless and scalable fashion.

## CloudFormation Quick Deploy

Use [CloudFormation Quick Deploy](https://us-east-1.console.aws.amazon.com/cloudformation/home?region=us-east-1#/stacks/quickcreate?templateURL=https://s3.amazonaws.com/grax-public-templates/master/cloudformation/lakehouse.yml\&stackName=lakehouse) to set up a Lakehouse.

You will need to switch to the correct region that your GRAX deployment and data is in.

By default the stack creates a new S3 Bucket, Glue Data Catalog and Athena Database all configured properly for storing and querying data.

Connect the S3 Bucket to GRAX with the provide Role ARN.

### Existing Bucket

If you already have a bucket with GRAX data, fill in `S3BucketName` .

The template will configure Glue and Athena to use the existing bucket and data.

<figure><img src="/files/7wM9tYK1XZnPb080R6Gs" alt=""><figcaption></figcaption></figure>

After you create the stack you will need to configure your bucket to send event notifications to the SQS queue in `SQSQueueArn` output. If your org ID is `00D46000001EXAMPLE`, use `parquet/v2/ORG%3D00D46000001EXAMPLE` as your notification prefix filter to avoid issues with the `=` special character.

{% embed url="<https://docs.aws.amazon.com/AmazonS3/latest/userguide/how-to-enable-disable-notification-intro.html>" %}

{% embed url="<https://docs.aws.amazon.com/AmazonS3/latest/userguide/enable-event-notifications.html>" %}

### IAM Access Keys

To connect the lakehouse to an external system like Metabase or your laptop, set `S3AccessMethod` to `User` . The IAM key and secret is available in Secrets Manager.

<figure><img src="/files/ChRcX22YiwTeIEpXvMLj" alt=""><figcaption></figcaption></figure>

## Query

Next configure an environment with your data lake credentials, then list what objects are in your data lake.

```bash
# configure AWS credential chain
export AWS_ACCESS_KEY_ID=AKIA4WWOSMD6PEXAMPLE
export AWS_SECRET_ACCESS_KEY=<REDACTED>
export AWS_REGION=us-east-1
export BUCKET=my-grax-bucket
export ORG=00D46000001EXAMPLE
```

Finally we can query our data lake with `aws athena`. First we count how many Account versions we have and select one record:

```bash
QUERY="SELECT COUNT(*) FROM object_account"

aws athena start-query-execution \
   --query-string $QUERY \
   --query-execution-context Database=default \
   --result-configuration OutputLocation=s3://$BUCKET/athena-results \
   --output text

654059a8-8455-4ecf-b539-3a694847aa15

aws athena get-query-results --query-execution-id 654059a8-8455-4ecf-b539-3a694847aa15
```

```json
{
  "ResultSet": {
    "Rows": [
      {
        "Data": [
          {
            "VarCharValue": "_col0"
          }
        ]
      },
      {
        "Data": [
          {
            "VarCharValue": "126178"
          }
        ]
      }
    ]
  }
}
```

```bash
QUERY="SELECT Id, Name FROM object_account LIMIT 1"

aws athena start-query-execution \
   --query-string $QUERY \
   --query-execution-context Database=default \
   --result-configuration OutputLocation=s3://$BUCKET/athena-results \
   --output text

f7717a2a-19ef-4b81-9d1a-858abb847a6a

aws athena get-query-results --query-execution-id f7717a2a-19ef-4b81-9d1a-858abb847a6a
```

```json
{
  "ResultSet": {
    "Rows": [
      {
        "Data": [
          {
            "VarCharValue": "Id"
          },
          {
            "VarCharValue": "Name"
          }
        ]
      },
      {
        "Data": [
          {
            "VarCharValue": "0014600000zEXAMPLE"
          },
          {
            "VarCharValue": "Example Acct"
          }
        ]
      }
    ]
  }
}
```

## Views

Your GRAX data lake has rows for every version of every record. However many analytics questions start by only looking at the most current "live" data. Here we create a view that reads all versions but returns just the latest "live" data.

```bash
QUERY="CREATE OR REPLACE VIEW object_account_live AS
WITH max_idseq AS (
  SELECT id AS mid, MAX(grax__idseq) AS max_idseq
  FROM object_account
  GROUP BY 1
),
live AS (
  SELECT *
  FROM object_account o
  JOIN max_idseq m ON m.mid = o.id
  AND grax__idseq = max_idseq
  AND grax__deleted IS NULL
)
SELECT * FROM live
"

aws athena start-query-execution \
   --query-string $QUERY \
   --query-execution-context Database=default \
   --result-configuration OutputLocation=s3://$BUCKET/athena-results \
   --output text
```

Now we can query the live data easily:

```bash
QUERY="SELECT COUNT(*) FROM object_account_live"

aws athena start-query-execution \
   --query-string $QUERY \
   --query-execution-context Database=default \
   --result-configuration OutputLocation=s3://$BUCKET/athena-results \
   --output text

e8a35172-27c2-418b-911b-7cd470837797

aws athena get-query-results --query-execution-id e8a35172-27c2-418b-911b-7cd470837797
```

```json
{
  "ResultSet": {
    "Rows": [
      {
        "Data": [
          {
            "VarCharValue": "_col0"
          }
        ]
      },
      {
        "Data": [
          {
            "VarCharValue": "23157"
          }
        ]
      }
    ]
  }
}
```

## Resetting Your Data Lake

First disable all objects in GRAX Data Lake. This stops new data from writing.

Next, clear out the Parquet data from S3:

```bash
aws s3 rm --recursive s3://$BUCKET/parquet/v2/org=00D46000001EXAMPLE/
```

Next delete all objects in GRAX Data Lake. This will reset objects back to the beginning of time.

Finally, re-enable all objects in GRAX Data Lake. This will rewrite all data from the beginning of time.


# AWS Data Lakehouse IAM Role

Some use cases for Data Lake Parquet files involve consuming that Parquet with a third-party tool. Care should be taken to consume these files securely and without exposing the rest of the data in the bucket. The steps below outline how to do this within AWS's S3 and IAM services. Steps may vary for other cloud providers and services.

{% hint style="warning" %}
**Cross Account Guide**

This guide assumes that the consuming Principal is in a different AWS Account than the one that owns the S3 Bucket. If the consuming Principal is in the same AWS Account as the one that owns the S3 Bucket, then the steps below can be simplified.
{% endhint %}

## Determine the Consuming Principal

The first step is to determine the Principal that will be consuming the Parquet files. This is typically an IAM user, role, or account. For the purposes of this example, we will assume the Principal is *anything* owned by a specific AWS Account.

## Set or Modify the S3 Bucket Policy

The next step is to set or modify the S3 Bucket Policy to allow the Principal to access the Parquet files. This can be done by adding a statement to the existing Bucket Policy or by creating a new Bucket Policy. If created anew, the Policy should look something like this with `[MY_BUCKET_NAME]` and `[AWS_ACCOUNT_NUMBER]` replaced with the appropriate values:

```json
{
    "Version": "2012-10-17",
    "Id": "Policy1611277539797",
    "Statement": [
        {
            "Sid": "Parquet_Cross_Account_ListBucket",
            "Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws:iam::[AWS_ACCOUNT_NUMBER]:root"
            },
            "Action": "s3:ListBucket",
            "Resource": "arn:aws:s3:::[MY_BUCKET_NAME]",
            "Condition": {
                "StringLike": {
                    "s3:prefix": "parquet/*"
                }
            }
        },
        {
            "Sid": "Parquet_Cross_Account_GetObject",
            "Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws:iam::[AWS_ACCOUNT_NUMBER]:root"
            },
            "Action": "s3:GetObject",
            "Resource": "arn:aws:s3:::[MY_BUCKET_NAME]/parquet/*"
        }
    ]
}
```

## Create an IAM Policy

The next step is to create an IAM Policy that allows the Principal to assume the role that will be created in the next step. The Policy should look something like this with `[MY_BUCKET_NAME]` replaced with the appropriate value:

```json
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "VisualEditor0",
            "Effect": "Allow",
            "Action": "s3:ListBucket",
            "Resource": "arn:aws:s3:::[MY_BUCKET_NAME]",
            "Condition": {
                "StringLike": {
                    "s3:prefix": "parquet/*"
                }
            }
        },
        {
            "Sid": "VisualEditor1",
            "Effect": "Allow",
            "Action": "s3:GetObject",
            "Resource": "arn:aws:s3:::[MY_BUCKET_NAME]/parquet/*"
        }
    ]
}
```

## Create an IAM Role

The next step is to create an IAM Role. The IAM Policy created above needs to be attached, and the Trust Policy needs to be set to allow the Principal to assume the role. The Trust Policy should look something like this with `[AWS_ACCOUNT_NUMBER]` replaced with the appropriate value:

```json
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "Parquet_Cross_Account",
            "Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws:iam::[AWS_ACCOUNT_NUMBER]:root"
            },
            "Action": "sts:AssumeRole"
        }
    ]
}
```

## Assume the Role

At this time, anything matching the allowed Principal scope can assume the role. The role must be assumed to have access; resources from that account will not be able to directly interact with the Parquet files.


# Snowflake Tables from Data Lake

This guide sets up a Snowflake integration that reads Salesforce data from your GRAX Data Lake S3 bucket, loads it into Snowflake tables, and keeps those tables refreshed on a schedule.

Every command runs inside a Snowflake worksheet except one edit to an AWS IAM role trust policy in Step 2. All SQL is given as copy-paste blocks; run them top-to-bottom.

The example names (`GRAX_DATA`, `GRAX_WH`, `GRAX_S3_INT`, etc.) can be changed to match your naming standards, but if you change one, update every occurrence. Values written as `<ALL_CAPS_IN_ANGLE_BRACKETS>` are placeholders you must replace with your own values before running the SQL.

## Before you start

Gather the items below. If anything is missing, stop here and contact GRAX Support or your AWS administrator.

| Item                             | Details                                                                                                                                                                                                                                                                                                                                                                   |
| -------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| S3 bucket name                   | The S3 bucket used by your GRAX application for the Data Lake. Available in your GRAX environment configuration.                                                                                                                                                                                                                                                          |
| Salesforce org ID                | The 15- or 18-character ID of the org whose data you want to load. Also in your GRAX environment configuration.                                                                                                                                                                                                                                                           |
| AWS IAM role ARN                 | A role Snowflake will assume to read from S3, with `s3:GetObject` and `s3:ListBucket` on the `parquet/v2/` prefix of the bucket. If you don't already have one, follow [Snowflake's S3 storage integration guide](https://docs.snowflake.com/en/user-guide/data-load-s3-config-storage-integration) (Steps 1 and 2 only; the rest is covered below), or ask GRAX Support. |
| AWS trust-policy edit access     | You will paste two values into that role's trust policy in Step 2. This is the only AWS-side change required.                                                                                                                                                                                                                                                             |
| Snowflake privileges             | `ACCOUNTADMIN`, or a role with `CREATE INTEGRATION` and `EXECUTE TASK` granted at the account level.                                                                                                                                                                                                                                                                      |
| Snowflake database and warehouse | Used to hold the tables and run the copy task. The examples below use `GRAX_DATA` and `GRAX_WH`. If you don't have them yet, create them with the block below the table.                                                                                                                                                                                                  |

```sql
CREATE DATABASE IF NOT EXISTS GRAX_DATA;
CREATE WAREHOUSE IF NOT EXISTS GRAX_WH
  WAREHOUSE_SIZE = 'XSMALL'
  AUTO_SUSPEND = 60
  AUTO_RESUME = TRUE;
```

The rest of this guide uses the `PUBLIC` schema, which exists by default in every Snowflake database, so no schema creation is needed. If you want to isolate this integration from other workloads in `GRAX_DATA`, create a dedicated schema now and substitute its name for `PUBLIC` everywhere below:

```sql
CREATE SCHEMA IF NOT EXISTS GRAX;
```

## Step 1: Create the storage integration

The storage integration is Snowflake's record of which AWS role it will assume and which S3 locations it is permitted to read. Replace the three placeholders below with the role ARN, bucket name, and Org ID you gathered above.

```sql
USE ROLE ACCOUNTADMIN;

CREATE STORAGE INTEGRATION GRAX_S3_INT
  TYPE = EXTERNAL_STAGE
  STORAGE_PROVIDER = 'S3'
  ENABLED = TRUE
  STORAGE_AWS_ROLE_ARN = '<YOUR_SNOWFLAKE_IAM_ROLE_ARN>'
  STORAGE_ALLOWED_LOCATIONS = ('s3://<YOUR_S3_BUCKET_NAME>/parquet/v2/org=<YOUR_SALESFORCE_ORG_ID>/');
```

## Step 2: Finish the AWS trust policy

The integration you just created has a generated IAM user and external ID. Paste both into the IAM role's trust policy so the role will accept Snowflake's assume-role calls.

```sql
DESC INTEGRATION GRAX_S3_INT;
```

From the output, note two values:

* `STORAGE_AWS_IAM_USER_ARN`, which looks like `arn:aws:iam::123456789012:user/abc1-s-v2st1234`
* `STORAGE_AWS_EXTERNAL_ID`, which looks like `ACME_SFCRole=1_abcDEF123...`

In the AWS console (or your preferred IAM tooling), edit the role's **trust policy** to match the block below, substituting both values:

```json
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "AWS": "<STORAGE_AWS_IAM_USER_ARN>"
      },
      "Action": "sts:AssumeRole",
      "Condition": {
        "StringEquals": {
          "sts:ExternalId": "<STORAGE_AWS_EXTERNAL_ID>"
        }
      }
    }
  ]
}
```

Save the trust policy. Snowflake validates the connection the first time it reads from S3, at the end of Step 3.

## Step 3: Create the schema, file format, and external stage

These three objects are the plumbing that turns the storage integration into something you can query. Replace the two placeholders with the same bucket name and Org ID you used in Step 1.

```sql
USE SCHEMA GRAX_DATA.PUBLIC;

CREATE OR REPLACE FILE FORMAT GRAX_PARQUET
  TYPE = PARQUET;

CREATE OR REPLACE STAGE GRAX_STAGE
  STORAGE_INTEGRATION = GRAX_S3_INT
  URL = 's3://<YOUR_S3_BUCKET_NAME>/parquet/v2/org=<YOUR_SALESFORCE_ORG_ID>/'
  FILE_FORMAT = GRAX_PARQUET;
```

Verify the connection by listing what the stage sees:

```sql
LIST @GRAX_STAGE;
```

You should get back Parquet files organized under `object=<SalesforceObjectName>/` prefixes (for example `object=Account/`, `object=Contact/`). Do not continue until `LIST @GRAX_STAGE` returns files; every later step depends on it.

## Step 4: Load your first object

This step creates a Snowflake table for the `Account` object and loads data into it. The `INFER_SCHEMA` function reads a sample of the Parquet files and generates the correct column definitions automatically, so you don't have to hand-write the schema. `MATCH_BY_COLUMN_NAME = CASE_INSENSITIVE` tells `COPY INTO` to map Parquet fields to Snowflake columns by name rather than position, which protects you from column-order changes in future GRAX exports.

```sql
CREATE TABLE IF NOT EXISTS GRAX_DATA.PUBLIC.ACCOUNT
USING TEMPLATE (
  SELECT ARRAY_AGG(OBJECT_CONSTRUCT(*))
  FROM TABLE(
    INFER_SCHEMA(
      LOCATION => '@GRAX_STAGE/object=Account/',
      FILE_FORMAT => 'GRAX_PARQUET'
    )
  )
);

ALTER TABLE GRAX_DATA.PUBLIC.ACCOUNT SET ENABLE_SCHEMA_EVOLUTION = TRUE;

COPY INTO GRAX_DATA.PUBLIC.ACCOUNT
FROM @GRAX_STAGE/object=Account/
FILE_FORMAT = (FORMAT_NAME = GRAX_PARQUET)
MATCH_BY_COLUMN_NAME = CASE_INSENSITIVE;
```

The block is safe to re-run. `CREATE TABLE IF NOT EXISTS` leaves an existing table untouched, `ALTER TABLE ... SET` is idempotent if already applied, and `COPY INTO` only loads files it hasn't loaded before. Schema evolution is enabled so new Salesforce fields appear as new columns on the next copy instead of breaking it.

To confirm it worked:

```sql
SELECT COUNT(*) FROM GRAX_DATA.PUBLIC.ACCOUNT;
SELECT * FROM GRAX_DATA.PUBLIC.ACCOUNT LIMIT 5;
```

To load another object, repeat the two statements above and change every occurrence of `Account` (case-sensitive, since it is part of the S3 path) and `ACCOUNT` (the Snowflake table name) to the Salesforce API name of the object you want, for example `Contact`, `Opportunity`, or `Lead`. The Salesforce API name is what GRAX uses as the folder name under `object=.../` in S3.

## Step 5: Automate ongoing refresh

Step 5 replaces the per-object `COPY INTO` from Step 4 with a stored procedure that loops over every object you care about, plus a scheduled task that runs the procedure on a cadence. The procedure uses `CREATE TABLE IF NOT EXISTS`, so it creates missing tables on first run and leaves existing ones alone, and it sets `ENABLE_SCHEMA_EVOLUTION = TRUE`, so new Salesforce fields appear as new columns without breaking the copy.

Edit the `ARRAY_CONSTRUCT(...)` list below to include every Salesforce object you want to keep in Snowflake.

```sql
CREATE OR REPLACE PROCEDURE GRAX_DATA.PUBLIC.INGEST()
RETURNS VARCHAR
LANGUAGE SQL
AS
$$
DECLARE
  stage   VARCHAR DEFAULT '@GRAX_DATA.PUBLIC.GRAX_STAGE';
  fmt     VARCHAR DEFAULT 'GRAX_DATA.PUBLIC.GRAX_PARQUET';
  tbl     VARCHAR;
  objects CURSOR FOR
    SELECT VALUE::VARCHAR AS name
    FROM TABLE(FLATTEN(ARRAY_CONSTRUCT(
      'Account',
      'Contact',
      'Opportunity'
      -- add more Salesforce object names here
    )));
BEGIN
  FOR obj IN objects DO
    tbl := 'GRAX_DATA.PUBLIC.' || obj.name;
    EXECUTE IMMEDIATE 'CREATE TABLE IF NOT EXISTS ' || tbl ||
      ' USING TEMPLATE (SELECT ARRAY_AGG(OBJECT_CONSTRUCT(*)) FROM TABLE(INFER_SCHEMA(' ||
      'LOCATION => ''' || stage || '/object=' || obj.name || '/'',' ||
      ' FILE_FORMAT => ''' || fmt || ''')))';
    EXECUTE IMMEDIATE 'ALTER TABLE ' || tbl || ' SET ENABLE_SCHEMA_EVOLUTION = TRUE';
    EXECUTE IMMEDIATE 'COPY INTO ' || tbl ||
      ' FROM ' || stage || '/object=' || obj.name || '/' ||
      ' FILE_FORMAT = (FORMAT_NAME = ''' || fmt || ''')' ||
      ' MATCH_BY_COLUMN_NAME = ''CASE_INSENSITIVE''';
  END FOR;
  RETURN 'Success';
END;
$$;
```

Create the task that calls the procedure on a schedule. The example runs every 60 minutes; adjust `SCHEDULE` if you want a different cadence.

```sql
CREATE OR REPLACE TASK GRAX_DATA.PUBLIC.INGEST_TASK
  WAREHOUSE = GRAX_WH
  SCHEDULE = '60 MINUTES'
AS
  CALL GRAX_DATA.PUBLIC.INGEST();

ALTER TASK GRAX_DATA.PUBLIC.INGEST_TASK RESUME;
```

To trigger the task immediately instead of waiting for the first scheduled run:

```sql
EXECUTE TASK GRAX_DATA.PUBLIC.INGEST_TASK;
```

## Verify and query

Check that the task is scheduled and see recent runs:

```sql
SHOW TASKS IN SCHEMA GRAX_DATA.PUBLIC;

SELECT *
FROM TABLE(INFORMATION_SCHEMA.TASK_HISTORY(
  SCHEDULED_TIME_RANGE_START => DATEADD('hour', -24, CURRENT_TIMESTAMP())
))
WHERE SCHEMA_NAME = 'PUBLIC'
ORDER BY SCHEDULED_TIME DESC;
```

Query your Salesforce data:

```sql
SELECT * FROM GRAX_DATA.PUBLIC.ACCOUNT LIMIT 10;
SELECT * FROM GRAX_DATA.PUBLIC.CONTACT LIMIT 10;
```


# Azure Data Lakehouse

GRAX Data Lake automatically organizes your CRM data as Parquet files in Azure Blob Storage for arbitrary on-demand analytics queries.

This guide demonstrates using Microsoft Synapse to query data it by SQL queries n a serverless fashion.

## Configure Azure

To start you need to log into the Azure console and find your resource group, storage account and blob storage used for GRAX.

The modifications that needed to be made to the blob storage:

1. (REQUIRED) The user to query the data needs the RoleAssignment “Storage Blob Data Contributor”. If you are unsure how to do this, please consult Azure documentation: [Assign an Azure role for access to blob data](https://learn.microsoft.com/en-us/azure/storage/blobs/assign-azure-role-data-access?tabs=portal])
2. (OPTIONAL) The IP of the computer being used needed to be added to the public access networking so the bucket could be viewed. This is not required for Synapse to view the data though.

Once this is done, log into a Synapse workspace, and attempt to run a query using the openrowset. If you don't have a Synapse workspace, you can follow these directions to create one in your resource group: [QuickStart: Create a Synapse workspace](https://learn.microsoft.com/en-us/azure/synapse-analytics/get-started-create-workspace).

In the example below, make sure the Account object has been turned on in Data Lake. This object could be substituted for any other object.

```mssql
select *
from openrowset(
  bulk 'https://{{STORAGE_ACCOUNT}}.blob.core.windows.net/{{STORAGE_CONTAINER}}/parquet/v2/org={{SALESFORCE_ORG_ID}}/object=Account/*/*.parquet',
  format = 'parquet') as rows
```

* BLOB\_STORAGE\_NAME - The name of the BLOB storage container that holds GRAX data.
* YOUR\_ORG\_ID - The Salesforce Id of your org

## Creating views

To accomplish this we need to create a database to house the views. By default Synapse will use the “master” database. Create a database for GRAX by following these steps:

1. Click on the data table
2. Click the + to add a new resource
3. Click SQL Database
4. Select Serverless and enter a name for the database

A view can now be created that abstracts away the openrowset:

```mssql
CREATE OR ALTER VIEW OBJECT_ACCOUNT AS
select *
from openrowset(
  bulk 'https://{{BLOB_STORAGE_NAME}}.blob.core.windows.net/grax/parquet/v2/org={{YOUR_ORG_ID}}/object=Account/*/*.parquet',
  format = 'parquet') as rows;
```

* BLOB\_STORAGE\_NAME - The name of the BLOB storage container that holds GRAX data.
* YOUR\_ORG\_ID - The Salesforce Id of your org

{% hint style="info" %}
The above instructions will get you started with Synapse and GRAX Data Lake. As your dataset grows in size, there will be other considerations needed, such as indexing which may necessitate a different approach or processing this data into an indexed destination table.
{% endhint %}


# DuckDB Data Lakehouse

GRAX Data Lake automatically replicates your Salesforce data as Parquet files in S3 for arbitrary on-demand analytics queries.

DuckDB lets you query your data lake data with a rich dialect of SQL from your laptop. First install it from [https://duckdb.org](https://duckdb.org/) or Mac Homebrew:

```bash
brew install duckdb
```

## IAM

Create a access key and secret with access to:

* S3 parquet data (read only)

First use an admin role to create a policy for the data lake access, then a user and access key with the policy.

```bash
export AWS_PROFILE=admin
export BUCKET=my-grax-bucket

cat >policy.json <<EOF
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "s3:ListBucket*",
        "s3:GetBucket*",
        "s3:GetObject"
      ],
      "Resource": [
        "arn:aws:s3:::$BUCKET",
        "arn:aws:s3:::$BUCKET/*"
      ]
    }
  ]
}
EOF

aws iam create-policy --policy-name datalake-duckdb --policy-document file://policy.json
aws iam create-user --user-name datalake-duckdb
aws iam attach-user-policy --user-name datalake-duckdb --policy-arn arn:aws:iam::873385320700:policy/datalake-duckdb
aws iam create-access-key --user-name datalake-duckdb
```

```json
{
    "AccessKey": {
        "UserName": "datalake-duckdb",
        "AccessKeyId": "AKIA4WWOSMD6PEXAMPLE",
        "Status": "Active",
        "SecretAccessKey": "<REDACTED>",
        "CreateDate": "2024-07-25T21:03:08+00:00"
    }
}
```

Save the access key and secret for next steps.

## Query

Next configure an environment with your data lake credentials, then list what objects are in your data lake.

```bash
# configure AWS credential chain
export AWS_ACCESS_KEY_ID=AKIA4WWOSMD6PEXAMPLE
export AWS_SECRET_ACCESS_KEY=<REDACTED>
export BUCKET=my-grax-bucket

# verify access and data lake data
aws s3 ls s3://$BUCKET/parquet/v2/
    PRE org=00D46000001EXAMPLE/

aws s3 ls s3://$BUCKET/parquet/v2/org=00D46000001EXAMPLE/
    PRE object=Account/
    PRE object=AccountContactRelation/
    PRE object=Asset/
    PRE object=Case/
    PRE object=Contact/
    PRE object=Opportunity/
    PRE object=User/
```

Finally we can query our data lake with `duckdb`. First we count how many Account versions we have and select one record:

```bash
duckdb grax.duckdb
```

```sql
-- use AWS env vars
CREATE OR REPLACE PERSISTENT SECRET s3 (TYPE S3, PROVIDER CREDENTIAL_CHAIN);

-- count all Account versions
SELECT COUNT(*) FROM READ_PARQUET("s3://my-grax-s3bucket/parquet/v2/org=00D46000001EXAMPLE/object=Account/**/*.parquet");

┌──────────────┐
│ count_star() │
│    int64     │
├──────────────┤
│       125562 │
└──────────────┘

SELECT Id, Name FROM READ_PARQUET("s3://my-grax-s3bucket/parquet/v2/org=00D46000001EXAMPLE/object=Account/**/*.parquet") LIMIT 1;

┌────────────────────┬──────────────┐
│         Id         │     Name     │
│      varchar       │   varchar    │
├────────────────────┼──────────────┤
│ 0014600000zEXAMPLE │ Example Acct │
└────────────────────┴──────────────┘
```

## Ad-Hoc Queries and Views

Your GRAX data lake has rows for every version of every record. However many analytics questions start by only looking at the most current "live" data. Here we create a view that reads all versions but returns just the latest "live" data.

```sql
CREATE OR REPLACE VIEW object_account_live AS
WITH object_account AS (
  SELECT * 
  FROM READ_PARQUET("s3://my-grax-s3bucket/parquet/v2/org=00D46000001EXAMPLE/object=Account/**/*.parquet")
),
object_account_max_idseq AS (
  SELECT id AS mid, MAX(grax__idseq) AS max_idseq
  FROM object_account
  GROUP BY 1
), 
object_account_live AS (
  SELECT *
  FROM object_account o
  JOIN object_account_max_idseq m ON m.mid = o.id
  AND grax__idseq = max_idseq
  AND grax__deleted IS NULL
)
SELECT * FROM object_account_live;
```

Now we can query the live data easily:

```sql
SELECT COUNT(*) FROM object_account_live;
┌──────────────┐
│ count_star() │
│    int64     │
├──────────────┤
│        23145 │
└──────────────┘

SELECT Id, Name, LastModifiedById, source__modified FROM object_account_live ORDER BY source__modified DESC LIMIT 1;

┌────────────────────┬───────────────┬────────────────────┬──────────────────────────┐
│         Id         │     Name      │  LastModifiedById  │     source__modified     │
│      varchar       │    varchar    │      varchar       │ timestamp with time zone │
├────────────────────┼───────────────┼────────────────────┼──────────────────────────┤
│ 0014600000zEXAMPLE │ Example Acct  │ 00546000001EXAMPLE │ 2024-07-25 10:31:06-07   │
└────────────────────┴───────────────┴────────────────────┴──────────────────────────┘
```

## Cached Data and Tables

Ad-hoc queries in the data lake are extremely powerful. As you ask questions of the data, you find common patterns that will be more efficient to cache locally versus always querying the data lake.

A common pattern with Salesforce data is turning user IDs into user names. We can easily create a persistent table with this data.

```sql
CREATE OR REPLACE TABLE user AS
WITH object_user AS (
  SELECT * FROM READ_PARQUET("s3://my-grax-s3bucket/parquet/v2/org=00D46000001EXAMPLE/object=User/**/*.parquet")
),
object_user_max AS (
  SELECT id AS mid, MAX(grax__idseq) AS max_idseq
  FROM object_user
  GROUP BY 1
), 
object_user_live AS (
  SELECT *
  FROM object_user o
  JOIN object_user_max m ON m.mid = o.id
  AND grax__idseq = max_idseq
  AND grax__deleted IS NULL
)
SELECT Id, Name FROM object_user_live;
```

Now when you specify the local `grax.duckdb` database, you can always query users quickly and without hitting the data lake at all.

```bash
duckdb grax.duckdb
```

```sql
SELECT COUNT(*) FROM user;
┌──────────────┐
│ count_star() │
│    int64     │
├──────────────┤
│          103 │
└──────────────┘

SELECT Id, Name, LastModifiedById, source__modified FROM object_account_live ORDER BY source__modified DESC LIMIT 1;
```

Finally we can mix and match, querying the data lake for Accounts and the local cache for users:

```sql
SELECT
  a.Id,
  a.Name,
  u.Name AS LastModifiedByName
FROM object_account_live a
JOIN user u ON u.Id = a.LastModifiedById
ORDER BY a.source__modified DESC
LIMIT 1;

┌────────────────────┬──────────────┬─────────────────────┐
│         Id         │  Name        │ LastModifiedByName  │
│      varchar       │ varchar      │       varchar       │
├────────────────────┼──────────────┼─────────────────────┤
│ 0014600000zEXAMPLE │ Example Acct │ Jane Example        │
└────────────────────┴──────────────┴─────────────────────┘
```


# GCP Data Lakehouse

The recommended data architecture on GCP is:

* Data Format: Parquet
* Storage: Google Cloud Storage (GCS)
* ETL: DataFlow
* Lakehouse: BigQuery

The recommended workflow is:

* GRAX writes data to GCS in Parquet
* Data Flow
  * Notified when new Parquet is available
  * Python script reads new Parquet data
  * Extracts objects and fields for downstream
  * Transforms fields into computed fields for business logic
  * Loads into Big Query
* Big Query
  * Queries and joins multiple data sets
    * GRAX ETL data
    * GRAX datalake data
    * Additional data sets

Anti-patterns are:

* Reading entire Parquet files vs specific columns
* Polling for new Parquet vs getting a push notification
* Moving GRAX data to track ingestion


# Heroku Data Lakehouse

GRAX Data Lake automatically organizes your CRM data as Parquet files in S3 for arbitrary on-demand analytics queries.

AWS Athena lets you query your data lake data by SQL queries that run on the Athena in a serverless and scalable fashion.

Heroku is a serverless PaaS (Platform as a Service) that allows you to deploy applications without worrying about the underlying infrastructure.

GRAX provides a Heroku Add-on to make querying your Athena Data Lake easy.

## Connection Details

When you add the GRAX Data Lake add-on to your Heroku application, it exposes environment variables that allow you to make an AWS Athena connection.

They are:

```bash
GRAX_AWS_ACCESS_KEY_ID=
GRAX_AWS_SECRET_ACCESS_KEY=
GRAX_AWS_REGION=
GRAX_S3_STAGING_DIR=
GRAX_ATHENA_WORKGROUP=
GRAX_ATHENA_DATABASE=
```

## Jupyter Notebook

You can deploy a configurable JupyterHub installation that expects the add-on environment variables from the add-on and automatically configures a client that returns a pandas data frame.

[![Deploy to Heroku](https://www.herokucdn.com/deploy/button.png)](https://www.heroku.com/deploy/?template=https://github.com/graxlabs/grax-jupyter/tree/main)

```python
import grax_athena
df = grax_athena.query_data_lake("SELECT COUNT(*) FROM object_account")
```

## Connecting from Python

You can use any Athena client to connect to and query the data lake. Here is an example using the `pyathena` client:

```python
import os
from pyathena import connect

# Retrieve AWS credentials from environment variables
aws_access_key_id = os.environ.get('GRAX_AWS_ACCESS_KEY_ID')
aws_secret_access_key = os.environ.get('GRAX_AWS_SECRET_ACCESS_KEY')
aws_region = os.environ.get('GRAX_AWS_REGION', 'us-east-1')

# Athena connection parameters
s3_staging_dir = os.environ.get('GRAX_S3_STAGING_DIR')
athena_database = os.environ.get('GRAX_ATHENA_DATABASE')
athena_workgroup = os.environ.get('GRAX_ATHENA_WORKGROUP')

# Establish connection to Athena
conn = connect(aws_access_key_id=aws_access_key_id,
                aws_secret_access_key=aws_secret_access_key,
                s3_staging_dir=s3_staging_dir,
                work_group=athena_workgroup,
                region_name=aws_region)
print("Connection to Athena established successfully.")

# Execute the query
cursor = conn.cursor()
query = f"SELECT COUNT(*) FROM {athena_database}.\"object_account\""
cursor.execute(query)

# Fetch and print the result
result = cursor.fetchone()
count = result[0]
print(f"Number of rows in object_account: {count}")
```


# Open Source Lakehouse

The recommended data architecture with free and open source tools is is:

* Data Format: Parquet
* Storage: Local folders or Minio S3 Compatible
* ETL: Apache Air Flow
* Lakehouse: DuckDB


# Data Cloud

Connecting GRAX Data Lake to SFDC Data Cloud

GRAX can connect to Salesforce Data Cloud to enable bidirectional data flow between your GRAX Data Lake and Salesforce's Customer 360 platform. This integration allows you to leverage GRAX's historical data within Data Cloud for analytics, segmentation, and activation.

## Prerequisites

* Active Salesforce Data Cloud license
* GRAX deployment with configured storage (AWS S3, Azure, or GCP)
* Salesforce org with System Administrator access
* GRAX Data Lake enabled on your GRAX instance

## **Configuration Steps**

{% stepper %}
{% step %}

### Set Up Data Cloud Permissions

* Navigate to Setup > Users in your Salesforce org
* Ensure your user has the following permission sets:
  * Data Cloud Admin
  * Data Cloud User
  * GRAX Agent Action (if using GRAX automation)
  * GRAX Console Admin Permission
  * GRAX Console Power Permission
    {% endstep %}

{% step %}

### Create a Data Connector in Data Cloud

* Open Data Cloud Setup from the App Launcher
* Navigate to Connectors under External Integrations
* Click "New" and select your storage type (e.g., Amazon S3 for GRAX on AWS)
* Choose "Source" as the connector type
  {% endstep %}

{% step %}

### Configure Authentication

* For AWS S3 connections:
  * Select "Access Key/Secret Based" authentication
  * Enter your AWS access key and secret access key
  * Specify bucket name and parent directory (typically `parquet/` for GRAX Data Lake)
* For Azure or GCP, use appropriate authentication methods
* Test the connection before saving
  {% endstep %}

{% step %}

### Create a Data Stream

* Navigate to Data Streams in Data Cloud
* Click "New Data Stream"
* Select your configured connector
* Choose Parquet as the file type
* Specify the file path pattern for GRAX data (format: `v2/org={OrgId}/object={ObjectName}/batch={BatchId}/data-*.parquet`)
  {% endstep %}

{% step %}

### Configure Data Lake Objects

* Select "Profile" as the category for customer data
* Map source fields to Data Cloud fields
* Set appropriate data types for each field
* Configure primary key (typically record Id)
* Set record modified field for incremental updates
  {% endstep %}
  {% endstepper %}

## **Important Considerations**

### **Field Naming Limitations**

* Data Cloud has a 40-character limit for field API names
* GRAX's nested field notation may exceed this limit
* Solution: Create field aliases in Data Cloud or use formula fields to reference long field names

### **File Path Structure**

GRAX stores data in a specific directory structure:

```
/parquet/v2/org={OrgId}/object={ObjectName}/batch={BatchId}/
```

Ensure your Data Stream configuration accounts for this pattern.

### **Data Sync Frequency**

* GRAX backs up data based on your configured schedule
* Data Cloud ingestion can be set to run hourly, daily, or on-demand
* Align these schedules for optimal data freshness

## **Troubleshooting**

### **"File not found" errors**

* Verify the exact file path in your S3/Azure/GCP bucket
* Check that the parent directory in your connector matches GRAX's structure
* Ensure proper wildcards are used in file name patterns

### **Authentication failures**

* Confirm IAM policies include s3:GetObject and s3:ListBucket permissions
* For Azure, verify SAS token or service principal has appropriate access
* Test connection directly from Data Cloud connector settings

### **Field mapping issues**

* Review field character limits (40 characters max)
* Check data type compatibility between GRAX and Data Cloud
* Use Data Cloud's formula fields for complex transformations

## **Next Steps**

Once connected, you can:

* Create unified customer profiles combining current Salesforce data with GRAX historical data
* Build segments using historical trends and patterns
* Activate historical insights through Marketing Cloud, Service Cloud, or other channels
* Use Data Cloud's Identity Resolution to match records across time periods

This integration complements GRAX's native analytics capabilities by making historical data available within Salesforce's ecosystem for real-time activation and decisioning.


# Multiple Orgs

Best practices for connecting GRAX to multiple Salesforce Organizations

## GRAX Backup

Each GRAX instance is designed to backup a single Salesforce organization. When backing up multiple organizations, we recommend a single GRAX instance and storage container per organization.

## GRAX Data Lake

The GRAX Data Lake is written to the same storage container as your GRAX instance. You can query multiple GRAX Data Lake data sets with a single query engine such as Athena/Glue, DuckDB, Salesforce DataCloud, and BigQuery.


# Migrating from Data Lake v1 to Data Lake v2

This guide walks through the recommended process for migrating from Data Lake v1 to Data Lake v2 in GRAX, including configuration steps, sequencing, and data retention considerations.

## Overview

[Data Lake v2](https://documentation.grax.com/reuse-data/data-lake) provides improved functionality and flexibility over [Data Lake v1.](https://documentation.grax.com/reuse-data/data-lake/data-lake-v1) The migration process is designed to allow you to enable Data Lake v2 alongside Data Lake v1, validate data, and then safely disable Data Lake v1 without data loss.

## Migration Process

GRAX has already enabled Data Lake v2 for users currently on Data Lake v1 and ensured that all objects enabled in v1 are also enabled in v2.

### Step 1: Monitor Initial Backfill

During the initial backfill, objects will show a `Processing` status.

Once the backfill is complete and the object status shows `Current`, Data Lake v2 is fully populated and up to date for that object.

### Step 2: Prepare Downstream Processing

{% hint style="danger" %}
This step is critical to prevent data loss or processing gaps.
{% endhint %}

Before disabling Data Lake v1, ensure the following are complete for Data Lake v2:

* Any processing rules are enabled
* Any triggers or automations are configured
* Any pipelines, queries, or downstream consumers are updated to reference Data Lake v2 data

### Step 3: Disable Objects in Data Lake v1

After confirming the following, you may safely disable the corresponding object in Data Lake v1:

* The object is Current in Data Lake v2, and
* You no longer need Data Lake v1 data for that object

To disable objects in Data Lake v1, take the following steps:

* Click `Configure` in the upper-right corner of the page
* Use the arrow icons (`<`, `>`) located between the columns to move all enabled objects into the column on the left
* Click `Save`

Once all enabled objects have been disabled, please reach out to <help@grax.com> and we’ll set Data Lake v2 as your default version.

{% hint style="info" %}
The migration is not considered complete until all of the enabled objects in Data Lake v1 have been disabled.
{% endhint %}

## Data Retention and Cleanup Considerations

* Data Lake v1 data remains in your storage bucket after disabling v1.
* GRAX recommends leaving v1 data in place for a period of time to support validation, rollback, or historical reference.
* You are free to delete Data Lake v1 data at any time once:
  * You have migrated objects to v2, and
  * Your pipelines and queries have been updated to use v2 data

{% hint style="danger" %}
When deleting, be sure to **only** delete files under `parquet/org=X/...` in your bucket. Do not delete files in other parts of the bucket.
{% endhint %}

## Getting Help

If you have questions about your specific migration path or would like assistance validating your setup, please reach out to the GRAX Support team:

* Visit: <https://documentation.grax.com/support/get-support>
* Email: <help@grax.com>
* Support is available to assist with migration issues


# Data Lake v1

{% hint style="danger" %}
GRAX is retiring the Data Lake v1 functionality in favor of the newer, faster, and safer [Data Lake v2](https://documentation.grax.com/reuse-data/data-lake).

For additional details, please see our retirement notice [here](https://documentation.grax.com/reuse-data/data-lake/migrating-from-data-lake-v1-to-data-lake-v2).
{% endhint %}

GRAX Data Lake lets you drive any type of downstream consumption of backed up or archived data with your GRAX dataset. By designating a set of objects for automated continuous export to Parquet format, you can create a valuable data source for applications like AWS Glue and further data analytics tools.

With Data Lake you can take control of your historical data, and do more with it throughout your enterprise. Whether you're looking to load data into a central warehouse, or feed an analytics platform such as Tableau, AWS QuickSight or PowerBI the Data Lake facilitates easy data movement with minimal configuration and setup.

What's more is that you access to your *entire historical data set*, not just the latest version.

## How It Works

Once enabled, Data Lake continuously monitors the GRAX Vault for new data. When it finds data, and it's safe to write, it is written to parquet format as detailed below. Every backed up version of a record for an enabled object is included.

### Data Structure

As is the case for backup data, the Data Lake writes parquet files to your configured object store, typically AWS S3 or Azure Blob Storage.

In modern object stores, we can use object key naming schemes to take advantage of the massive read/write scalability of these services. Furthermore, many of the data lake applications that would typically be employed in ingesting and processing Data Lake data supports common naming conventions to assist with efficiently recognizing and ingesting new data. With these two considerations in mind, we structure our Data Lake data as follows:

`parquet/org=1234/object=myObject/day=nn/hour=nn`

* `parquet` is the top level directory present in the object storage bucket. All Data Lake data goes here. You don't need to create this "folder," it is created automatically.
* `org` represents the unique ID of your Salesforce org
* `object` is the name of your enabled object. If you have multiple objects configured for Data Lake, you can see a directory for each in here.
* `day` is the day the data was written to the GRAX Vault. Depending on your backup job configuration, you may not have data for every day. You'll see a directory for each day where data was backed up.
* `hour` is the hour data was written to the GRAX vault. If you have hourly backups enabled, you might see as many as 24 directories in here.

{% hint style="info" %}
Times are in UTC
{% endhint %}

### Configuring Objects

For an object to be included in the Data Lake, you have to explicitly turn it on. Any object that's supported for backup works.

With the new GRAX Application, the `Data Lake` tab provides the ability to:

* Enable objects for Data Lake
* View which objects have been enabled
* View their `last write` time. This is the most recent time that new data for the specific objects was found in the GRAX data vault and written to the Data Lake parquet directories
* See metrics for the number of records written in the last write and all time

![Data Lake Status Page](/files/HVPfrdr3XtDey7Shb72H)

### Verify That It's Working

Once configured for one or more objects, Data Lake process automatically starts running every 5 minutes. Here's what to expect and how to verify that it's working:

* After the first run, that is 5-10 minutes after the feature was turned on, run you should see the `parquet` directory created in your object storage bucket. It may take some time for object data to show up. See below for an explanation of what to expect.

### When To Expect Data

As mentioned, we partition data by hour. Once the Data Lake has written data for a particular hour for a specific object it sets an internal watermark to keep track of where to start from on the next run.

So, if we just wrote data for hour=20 on a given day, the next run is going to start looking for data that was written in hour=21. Thus, when we write data for hour=20, we have to make sure no additional data can come in for this hour. Otherwise we might miss data on the next run. Currently, we accomplish this by *writing data for a given hour 15 minutes after the hour*.

{% hint style="info" %}
It may take two hours for your first data to appear in the Data Lake
{% endhint %}

#### Conducting a Basic Data Check

Once you've got everything set up, it's always nice to conduct a basic check to see that everything is as expected before configuring any downstream integrations etc. Here are a couple of ways to do that:

#### **Downloading and Checking a Parquet file from S3**

1. Log in to the AWS Console
2. Navigate to the bucket you have configured for GRAX
3. Traverse the Data Lake directory hierarchy, and locate an hourly partition with data in it. You'll see a file named something like `data-00000.parquet`
4. From "Object Actions" menu, select "Download"

Once the file is downloaded to your computer, you can use a command-line utility such as [parquet-tools](https://pypi.org/project/parquet-tools/) to print its contents:

```shell
% parquet-tools cat data-00000.parquet
Title = Senior Editor
LastName = Iiannone
Id = 0035e000001uC6AAAU
SystemModstamp = 2021-04-30T20:14:14.000Z
FirstName = Jobyna
IsDeleted = false
OwnerId = 0055e000001D8WEAA0
PhotoUrl = /services/images/photo/0035e000001uC6AAAU
LastModifiedDate = 2021-04-30T20:14:14.000Z
IsEmailBounced = false
Name = Jobyna Iiannone
AccountId = 0015e0000043cIcAAI
CleanStatus = Pending
CreatedDate = 2021-04-30T20:14:14.000Z
LastModifiedById = 0055e000001D8WEAA0
CreatedById = 0055e000001D8WEAA0
Email = jiiannone0@csmonitor.com
```

#### **Using S3 Select**

[S3 Select](https://www.google.com/url?sa=t\&rct=j\&q=\&esrc=s\&source=web\&cd=\&ved=2ahUKEwizxNyfjuPwAhU6JzQIHQIXDr8QFjAAegQIAxAD\&url=https%3A%2F%2Faws.amazon.com%2Fblogs%2Faws%2Fs3-glacier-select%2F\&usg=AOvVaw27UroURQd3S0pwOrBefMQ2) is a recent addition to the AWS S3 feature set that allows you to issue SQL queries directly against objects stored in S3. Parquet is one of the formats supported by this feature. Here's how you use it:

1. Log in to the AWS Console and navigate to S3
2. Locate an hourly partition with data in it
3. In the "Object Actions" menu, select "Query with S3 Select"
4. On the next screen, make sure the input format is "Apache Parquet" and set output to "CSV"
5. Run the default query to return the first 5 records from the file.

![S3 Select Configuration (AWS Console)](/files/PGM5i1V5sVjz33yt050Q)

## Useful to Know

#### Limits

{% hint style="info" %}
The Data Lake currently supports up to 100 enabled objects. If you need additional objects enabled, please contact your GRAX Account Manager.
{% endhint %}

#### The GRAX Parquet Format

Data Lake data is written in [Apache Parquet](https://parquet.apache.org) format. One of the advantages of Parquet vs other interchange formats like CSV, is that you can encode schema with the object data. It also supports excellent compression. Parquet is well supported by all major ETL, data storage and data processing platforms.

#### **Salesforce Data Types vs Parquet Data Types**

In version 1.0 of the Data Lake all Salesforce field data types are treated as Strings in Parquet. We do this to allow the smoothest integration with ETL tooling like [AWS Glue](https://aws.amazon.com/glue), knowing that most of our customers want to stage schemas to their preference once the data is on-boarded in the data lake or analytics warehouse.

#### **GRAX Metadata Fields**

In addition to the Salesforce object data embedded in the parquet files, GRAX adds the following metadata fields prefixed by `grax__`:

* `grax__added` Parquet timestamp format indicated when the record was written to the GRAX Vault.
* `grax__deleted` Parquet timestamp format indicated when the record was deleted from Salesforce.
* `grax__deletesource` String indicating whether the record was deleted by `grax` or `salesforce`.

Dates are stored in [Unix Timestamp](https://en.wikipedia.org/wiki/Unix_time) format in milliseconds. The integer is the number of milliseconds since midnight on the first of January, 1970.

{% hint style="info" %}
**Converting Timestamps to Readable Dates**

You may need to do some conversion to turn UNIX timestamps into easily readable dates. Fortunately, this is quite simple to do. For example, in AWS Athena you can use the following conversion function to display the grax\_\_added metadata field as a readable date:

```sql
select from_unixtime(grax__added / 1000) AS readableDate from mytable
```

This would yield dates in a format like this:

```
2021-05-10 22:23:52.000
```

Note that this is still in UTC.
{% endhint %}

#### Managing Duplicates

A fundamental principle of the Data Lake is that you get all the versions of all records that we have stored for enabled objects. Ultimately this feature is what enables you to accurately analyze how your data evolves over time. Because of this, some amount of duplicate records in the parquet extracts are inevitable and expected; your reports, queries etc. need to account for duplicates accordingly.

The following GRAX behaviors can result in duplicate records (at the Salesforce data level):

* *Full Backups:* Running on-demand or periodic full backups for an object captures a new version for each included record, regardless of whether we already have a version in storage with the same LastModifiedDate or SystemModstamp.
* *Archiving:* As the first step of an archive process, GRAX captures a full backup of the current state of each included record. Even if the record did not change, this results in a duplicate version.
* *Delete Tracking:* GRAX performs periodic delete tracking. When we detect a deleted record, we add GRAX metadata to capture the time of the delete. Because this is purely GRAX metadata, the SysModStamp/LastModified fields won't change, but you get a new version with a timestamp value in `grax__deleted`:

![Example of "Duplicate" Rows in Parquet](/files/zjd33HumQLjoX870tdC9)

## Working with Data Lake Data

Now that Data Lake is turned on, you're ready to make use of your data in other systems. We've built this feature to support any type of data lake or analytics platform with minimal effort. Here are some examples of integrating with the most popular targets for Data Lake data:

* Crawling Data Lake data with AWS Glue
* Converting historical data to CSV with AWS Glue
* Loading data into AWS Redshift
* SQL queries on the Data Lake with AWS Athena
* Reporting on archived data with Tableau CRM
* Visualizing historical data in Tableau Desktop/Online
* Analyzing historical data with AWS QuickSight
* Loading historical data into Microsoft Azure Synapse Analytics


# Global Search

Utilize the `Global Search` functionality to find specific data within large data sets.

## Performing a Global Search

To start a `Global Search`, navigate to the `Global Search` section within the GRAX Application. You will be required to select the `Related Object` and `Record Status`, then populate the `Date Filter` criteria to narrow the search. The data is viewable, available for download, and interactable with GRAX features such as Archive and Restore.

{% hint style="info" %}
Global Search results will be deleted after 60 days of inactivity.
{% endhint %}

#### Optional Field Filters

Optional field filters allow you to add specific field values that govern the results your search will provide. Each field filter value must be located on an individual line item for accurate results.

#### **Mode**

Selecting an option from the `Mode` dropdown menu will determine filter logic. Selection options include:

* `Match any filter (OR)` will return results where one or both of the filters are true.
* `Match all filters (AND)` will return results where both of the filters are true.
* `Match by custom groups` can be used to build more precise or flexible conditions/rules.

<figure><img src="/files/NjEfKS9wJiF2HMZKoLBT" alt=""><figcaption><p>Search Filters</p></figcaption></figure>

#### **Search Operators**

When adding optional field filters, you will be prompted to select an operator from the dropdown menu.

{% hint style="info" %}
The `Less Than`, `Less Than or Equal`, `Greater Than`, and `Greater Than or Equal` operators compare values lexically, and string comparison is case insensitive. Example: 9 comes after 10.
{% endhint %}

#### **Other Options**

Additionally, you have the ability to:

* Set a limit for the number of results produced by the search.
* Run the search in reverse order with the oldest results appearing first.
* Send a notification email to the admin users once the job has completed.

<figure><img src="/files/uIXLbbXzy8w4Edrz1Fpf" alt=""><figcaption><p>Other Search Options</p></figcaption></figure>

## Search Results List

Once the Global Search has completed, you will be able to see the details of the search job and a list of the results. These result records can then be modified (either individually or in batches), archived, restored, seeded, or purged depending on the current status of the record.

To modify record(s), click the checkbox on the left to select the record(s) and then click the pink `Modify records` button:

<figure><img src="/files/30PH7smJ7DjfQJ0wRd6w" alt=""><figcaption></figcaption></figure>

### Customizing Fields

You can configure which fields appear in the results list by clicking the `Customize fields` button located between the search criteria and the search results.

<figure><img src="/files/8E0TGhMZJDI9A9RLuqog" alt=""><figcaption></figcaption></figure>

From here, you can choose which fields to display in the results list or include in a CSV download.

### Downloading Results

After a search has completed, results can be downloaded in CSV format. When choosing to download search results, users are prompted to select which version of the results they'd like to download. The options are:

* `Visible Fields`: The CSV will only include the fields that are visible on the Search results page. By default, this is a subset of fields that contains `Id`, `Name`, and several audit/timestamp fields, but this can be customized.
* `All Fields`: All fields from the records are included in the download.

{% hint style="info" %}
*Depending on the number of records and fields included in the download, the Global Search results may take several minutes to download. If your search results exceed a size that's easily workable in common tools like Excel or Google Sheets, try a more powerful tool like SQLite.*
{% endhint %}

## Indexing Fields

The `Index` search functionality offers improved search speed for customers who commonly search on the same fields and need results quickly. When a field is indexed, comparisons against that field's value on any given record can be processed more quickly. Indexes are specific to the field and object pair chosen for each, and users can create custom-indexed fields.

#### When to Index Fields

Only fields that are used the most frequently should be indexed. While there is no limit to the number of fields you can index, indexing multiple fields at the same time will result in longer processing times. We recommend starting with the highest priority objects/fields first and adding additional fields for indexing as needed.

#### How to Index Fields

From the Global Search page, click the `Indexes` button. To add an index, select the object and field, then click save to start the indexing process.

<figure><img src="/files/MQkpYjtfWSg9ZVgJF8y4" alt=""><figcaption><p>Managing Search Indexes</p></figcaption></figure>

Once an index is created, it will be continuously updated and automatically used whenever possible in all future searches. Indexes will be available to all users and used in all subsequent searches, regardless of who initiated the index. This does not grant all users the ability to see or search on the field; it only allows all users to take advantage of the index if they have access to the field.

The `Search Indexes` page (`Global Search` > `Indexes` > `Search Indexes`) offers the ability to reorder index priorities (by dragging rows), and track the status of the indexing process.

## Search Templates

### What are Search Templates?

Search Templates enable administrators to create and share pre-configured search queries within the GRAX interface, harnessing the full power of standard GRAX Search functionality. Designed to simplify access to archived and backed-up Salesforce data, these templates make it easy for non-technical users to quickly locate the information they need without the need to construct complex queries.

For even easier access, Search Templates can also be added as a dedicated tab within Salesforce, allowing users to run searches directly from their familiar workspace without navigating away from Salesforce.

### Key Benefits

* Fast, consistent access to historical data: Search Templates eliminate guesswork by standardizing how end users in SFDC locate archived records such as past cases, emails, or account activities. This ensures quick, repeatable access to customer history, even across teams and shifts.
* Templates lower the barrier for new hires by removing the need to learn more complex search logic.
* Templates reduce the chance of user error when searching for data - ensuring users don’t overlook key information due to misconfigured filters.

### Common Use-Case Examples

* Search by Case Number to Retrieve Archived Support Cases - Search Template:
  * The `Archived Case Lookup by Case Number Search` enables users to quickly locate older cases that have been archived - often critical for understanding prior resolutions, re-opened issues, or compliance reviews.
* Search Email Records for Specific Keywords - Search Template:
  * The `Email Body Keyword Search` lets users search through archived email communications using relevant keywords (e.g., `refund`, `escalation`, `outage`) to find specific interactions or topics.

### How do I get started?

#### Create a New Search Template in GRAX

* Within the GRAX Application, navigate to the `Global Search` tab
* Click the `Templates button`
* Select `New`
* Populate the required fields:
  * **Template Name** – A clear, descriptive name for end users (e.g., `Find Case by Case Number`)
  * **Description** – Brief explanation of what the template does
  * **Visible to all users** – Check this box to make the template available to other users
  * **Single record** – Check this if the search is expected to return only one result (e.g., searching by `Case Number` or `Account Name`). This improves performance
  * **Object to search** – Select the Salesforce object (e.g., `Case`, `Contact`, `Order`) from your GRAX archive
  * **Record Status** – Choose which data set to search:
    * `All,` `Live`, `Deleted, or Archived`
  * **User input fields** – Add the fields users will fill in to perform the search (e.g., `Email`, `Case Number`, `Account Name`)
* Click `Save` to publish the template. Once saved, the template will be available as a selectable option in both the user’s SFDC GRAX Search tab and the GRAX Application:

<figure><img src="https://lh7-rt.googleusercontent.com/docsz/AD_4nXcOMhhGtaono7p8nzOR4_1y7qsT4u0mFON1tXD2D-vPLnBuTxEremZza-IWjo2qCQeFTwxBCsiiBeX4eiJUdn0C9IfMwknl1w4KOeO8rVfL5IaulwOPn7YKEzcVBEVe3dY-Xvbj_g?key=rf8rPY1LqQjo6Fht0MNkpw" alt=""><figcaption></figcaption></figure>

{% hint style="info" %}
Fields used in Search Templates must be indexed for optimum performance. Please see[ Indexing Fields](https://documentation.grax.com/reuse-data/global-search#indexing-fields) for more information. GRAX will index any fields used in Search Templates if not already indexed.
{% endhint %}

### Utilizing Search Templates

#### Utilizing Search Templates within the GRAX Application

* Once created, Search Templates can be accessed from within the GRAX Application by navigating to the `Global Search` tab and clicking the `Templates` button.
* Additionally, active Search Templates can be used in the GRAX Application by clicking the `New Search` button dropdown.

<figure><img src="https://lh7-rt.googleusercontent.com/docsz/AD_4nXdeB3dPP8e_CAGFLSyavLaZGoR5IE06MRuPuKLCggh5zD6ZD3JK1McpALO_KQS9ckQlvT8A7OuXGkFaVMGEvFSHCA5FbcH7BfOC2c4GPt43uiKasJBxClaD_YP54hP7jQoJvb0?key=rf8rPY1LqQjo6Fht0MNkpw" alt=""><figcaption></figcaption></figure>

#### Utilizing Search Templates within Salesforce

* Ensure that the [GRAX Salesforce Managed Package - Second Generation](https://documentation.grax.com/reuse-data/managed-package/second-generation) has been installed or updated to the latest version.
* Go to Salesforce Settings, Custom Settings, GRAX Settings, Click 'Manage' and enable the **Search Tab: Template Search.**

<figure><img src="/files/Ik84Pk2AapLGGtnczByk" alt=""><figcaption></figcaption></figure>

* Once the **Search Tab: Template Search** setting has been enabled in the GRAX managed package Custom Settings any active Search Templates can be seen on the `GRAX Search` tab:
* Add the GRAX Search Tab to the appropriate App in your Salesforce Environment.

<figure><img src="https://lh7-rt.googleusercontent.com/docsz/AD_4nXcFPjsryabDMjNMFib3P53Jf0I7YBB9YCPoKPSONpKoV_8PrAnJuBx-z5DzIdRGEdbtA1wXUjofocQvQ1KQGXsh4_kldGtiaUPDug-XcTFTsPvjGo8r4dhJDpqESwNlk2DVH-TJ?key=rf8rPY1LqQjo6Fht0MNkpw" alt=""><figcaption></figcaption></figure>

* Select a template and search for the desired criteria.
* The matching search results and related records will be retrieved and displayed:

<figure><img src="/files/p3uCpo08gaSMf7BO1c17" alt=""><figcaption></figcaption></figure>

<figure><img src="/files/vwF8D7VpcsxDyjD1dSW9" alt=""><figcaption></figcaption></figure>

## Global Search Best Practices

* Index commonly used fields for faster search results.
* Prioritize indexed fields for more efficient processing during indexing.
* Use Global Search to archive/restore records directly.
* Narrow the search criteria as much as possible.
* Re-run previous search jobs with the same search criteria.
* Edit the `Global Search` name for easy recognition.
* Delete searches that are no longer needed directly from within the search job.
* “Star” frequently used searches to have them appear at the top of the search job list.


# Sandbox Seeding

* Do you struggle with old, stale data and wish your developers could develop and test against the latest production data?
* Is your company behind on your Salesforce sandbox refresh cycle?
* Does your team struggle to follow a Salesforce DevOps process?
* Do your developers all work out of the same sandbox and step on each other's toes while trying to build, test, and ship their code?
* Do you need to anonymize data in lower sandboxes for training in compliance with privacy laws?

## Why should I use Sandbox Seeding?

GRAX Sandbox Seeding is built for Salesforce developers and the Salesforce administrators who support them. Seeding helps make your job easier to develop, iterate, test, retest, and ship your new feature or product improvement so you can get to market faster with higher quality results.

## What org types can I use Sandbox Seeding with?

GRAX Sandbox Seeding works with all Salesforce org types but immensely improves the experience with Developer and Developer Pro sandboxes, where Salesforce doesn't provide the tooling to propagate data as part of a template-driven refresh.

## How do I access GRAX Sandbox Seeding?

Sandbox Seeding is integrated in three places within the GRAX Application:

{% tabs %}
{% tab title="Sandbox Seeding Tab" %}
Click on Sandbox Seeding in the menu and you will see the button New Sandbox Seeding. This takes you into the Seeding workflow where we mirror our source selection user interface from Archive and provide users with the ability to select records with the familiar choices of Salesforce Report, SOQL Query, CSV, or list of record IDs.

<figure><img src="/files/xE0umPU3lme6Jm1fDPYn" alt=""><figcaption><p>Creating a Seeding Job via the Sandbox Seeding Tab</p></figcaption></figure>
{% endtab %}

{% tab title="Global Search" %}
A second entry point for Sandbox Seeding is Global Search. When you click on Global Search in the menu, you will see a table of previously run search jobs. You can create a New Global Search or use a previously run search to select data as the source. Use the checkboxes to select a subset of records or all records and then click the ‘Seed Records’ button to begin the Seeding workflow.

<figure><img src="/files/AtxG8TXeFSUqr6QS5JWt" alt=""><figcaption><p>Creating a Seeding Job via Global Search Results</p></figcaption></figure>

You have the option to tune the size of the graph by using the Maximum Child Level drop down. You also have the options to include archive and deleted records and to be notified by email on this seeding job. Click the save (disk) icon to make your chosen settings the default.

<figure><img src="/files/6VoWuIXhi3ySoiuzsGL5" alt=""><figcaption><p>Seeding Job Configuration from Global Search</p></figcaption></figure>
{% endtab %}

{% tab title="Record Details" %}
A third method of selecting records for Seeding can be accessed through record details. Either click on any record link or enter the ID in the Lookup By ID box in the header to arrive at the record details view. Clicking on the vertical ellipsis in the header gives you the option to seed. A modal pops up asking you to enter your credentials and presents a similar workflow as the other Seeding source selection methods.

<figure><img src="/files/J8AQKoV9rLGAvDXUZr64" alt=""><figcaption><p>Seeding a Record from the Record Details Page</p></figcaption></figure>
{% endtab %}
{% endtabs %}

## Overview

1. Create / refresh an empty Developer sandbox off your production Salesforce org
2. Ensure that the user executing the seed has the [Sandbox Seeding permission set](#seeding-permission-set)
3. Choose one record to seed (it's best to start small and see how things work in your org)
4. Follow the [Sandbox Seeding Workflow](#sandbox-seeding-workflow)
5. [Undo the seed, or Seed Again](/reuse-data/sandbox-seeding#optional-undo-seed-seed-again)

Once you are successful with the above steps, you are ready to move on to bigger and more realistic data sets. Remember, Salesforce data is complex, so it's best to start small.

### Seeding Permission Set

GRAX Sandbox Seeding can be enabled for users by adding the permission set: `GRAX Console Seeding Permission`. Contact your GRAX or Salesforce Administrator to request access to this permission set.

### Sandbox Seeding Workflow

GRAX Sandbox Seeding provides a workflow to guide you through the steps to seed data from a source to a destination org.

{% stepper %}
{% step %}

#### Select the Destination

Choose the seeding target that records will be created within. If you have seeded to this org previously, the seeding destination will be listed in the drop down. If this is your first time seeding to this org, click `Add Target Org.` Clicking this button pops up a modal asking for your target Org Type and the Salesforce login information for that org (either OAuth or username, password, and security token).

<figure><img src="/files/mUdKHi3BrZWJRIeeDh2m" alt=""><figcaption><p>Selecting Seeding Destination</p></figcaption></figure>
{% endstep %}

{% step %}

#### Select the Source

There are a variety of options for selecting the records from your main org that you want to seed into the destination. Choose and configure an available source:

{% hint style="info" %}
Please note GRAX allows seeding up to 10,000 parent records per seed.
{% endhint %}

<figure><img src="/files/2Z6NNlvOQGhnoktwJodG" alt=""><figcaption></figcaption></figure>
{% endstep %}

{% step %}

#### Configure Options

Choose seeding options. We provide several settings:

* You can tune the size of the seeding dataset through the `Maximum Child Level` option.
* When seeding from Search or Query WHERE, you can specify the maximum number of source records that you would like to seed.
* You can choose which objects to skip in your seed.
* You can include deleted and archived records.
* You can send an email notification of important changes.
* You can disable automated processes including triggers and field validation.

Data Anonymization

* **Preserve the data you are seeding** - Seed data without anonymization. Use this when working with non-sensitive data or in controlled environments.
* **Randomly anonymize the data** - Generates different anonymized values each time you seed. Best for development and training environments where data consistency across seeds isn't required.
* **Deterministically anonymize the data** - Generates the same anonymized values consistently across multiple seeds. Use this when you need to maintain data integrity with external systems or when seeding the same records into multiple environments.

Random and deterministically anonymized data generates fake data for fields of type currency, email, phone and URL. Also covers specific fields like first/last name, addresses and birthdates.

<figure><img src="/files/R6iDc1Rh4MHDFCkdTamq" alt=""><figcaption><p>Configuring Seeding Options</p></figcaption></figure>
{% endstep %}

{% step %}

#### Preparing the Hierarchy

GRAX builds and graphs the hierarchy of your records to prepare for seeding to the target org. If you used Global Search or the record details view as the Seeding source, you will start on this page of the workflow.

You will notice a Seeding data size estimate versus available space in the target org in the graph header. Use this to make sure your org has enough space for the Seeding data and any development or testing work you need to do.

<figure><img src="/files/DRTTrlEoX5wTveYoklvk" alt=""><figcaption><p>Prepared Seeding Record Hierarchy</p></figcaption></figure>

There is also a list view where you are presented with tools to configure the seed allowing you to skip records, set overrides, and include additional objects referenced by your seed data.

You may not want all objects that are referenced in the graph hierarchy. You have the option to skip objects that you don't wish to include.

<figure><img src="/files/L9xtsVCpnDtVXt6AfWTy" alt=""><figcaption><p>Alternate List View with Additional Options</p></figcaption></figure>

Salesforce requires that we maintain referential integrity so certain objects that are referenced by other objects in your seeding data must be included with a seed or you will get an error. To resolve this, you can either include the referenced objects or set an override. Overrides allow you to reference an object that is already in the target org or the seeding data set. We automatically include referenced parent records that are required by Salesforce to reduce the need to set overrides.

<figure><img src="/files/m9VaqTNP3T4fOeOoYS34" alt=""><figcaption><p>Field/Value Overrides</p></figcaption></figure>

The relationships tab allows you to select related objects to bring along with the seed. If you experience an error due to a missing object, try including it with this tool.

<figure><img src="/files/5vFsDSt2H6N195WoNuEz" alt=""><figcaption><p>Optional Relationship Inclusion</p></figcaption></figure>
{% endstep %}

{% step %}

#### Seeding the Records

After clicking Seed, the GRAX Application prompts you to confirm and warns you if this is a Production org. You will be presented with a progress indicator as the data is seeded to your target org.

<figure><img src="/files/Ltpw8lv22ArxrTzcqXX0" alt=""><figcaption></figcaption></figure>
{% endstep %}

{% step %}

#### Optional: Undo Seed, Seed Again

The `Undo Seed` feature allows you to seed data to a sandbox, do experiments, test things, and then remove the data from the org.

The `Seed Again` button allows you to put a fresh copy of the data back into the sandbox to replay your tests.

<figure><img src="/files/Ltpw8lv22ArxrTzcqXX0" alt=""><figcaption></figcaption></figure>

If you have not yet undone a seed and click `Seed Again`, you will get a pop up modal warning that prompts you to undo that seed.

<figure><img src="/files/WQx33smCDaEsPpCV3bbm" alt=""><figcaption></figcaption></figure>

Additionally, you have the option to seed the same set of data to a different target org by clicking the caret icon on the `Seed Again` button and clicking `Seed to a Different Target Org.`

<figure><img src="/files/zYQ0CKXIg3keLXZvOcBm" alt=""><figcaption></figcaption></figure>

{% hint style="info" %}
If child records have been added to a parent record that was seeded, an error message will appear indicating that not all records could be removed. A list of the remaining records that need to be manually deleted in Salesforce will be provided.
{% endhint %}
{% endstep %}
{% endstepper %}

## Frequently Asked Questions

### Where can I see the list of Sandbox Seeding jobs?

Prior seeding jobs are shown in the `Sandbox Seeding` tab of the menu. Click on a prior Seeding job to see the job details, as well as an option to seed the data set again.

<figure><img src="/files/xE0umPU3lme6Jm1fDPYn" alt=""><figcaption><p>Seeding Jobs List</p></figcaption></figure>

### Where can I manage my Sandbox Seeding Target orgs?

This can be found within the `Archive, Restore & Seeding` section of the Settings page and allows you to see a list of connected target orgs, remove them, or add new target orgs.

<figure><img src="/files/SN0aklXQlAWyoNT9N3q3" alt=""><figcaption><p>Seeding Targets List</p></figcaption></figure>

You will also see an option for `Allowed Production Orgs`; adding a production org to this list will then allow you to add it to the `Sandbox Seed Targets` list, but this should be used with caution as seeding to a production org is not a regular use case.

### Why are some records \`Skipped\`?

If a completed seeding job shows that records have been skipped due to `mapped to existing record,` this indicates that there is already a record in your sandbox with the same id; this typically occurs with full copy sandboxes and records will not be seeded if there are existing records with the same ids in the target org.

### How does Sandbox Seeding handle duplicate records?

If seeding a record that has already been previously seeded, this will produce a duplicate record in the target org with a new ID and will result in two records with the same values and different IDs.

### How Does Seeding Handle Errors?

After a seeding operation, there is a results page that shows a summary of all the data creating including success and errors.

One of the most common sources of errors in seeding is conflicts from the target containing existing data. If this is due to a previous seed, you can use the "Undo Seed" tool which deletes everything created by the seed.

If this is not from a seed, you can delete data with an Apex script or other SFDC tooling then try again.

```apex
List<User> userList = [Select Id from User where Alias='GSale'];
if (userList.size()>0){
    System.debug('Deleting Everything Created By: ' + userList[0].Id);
    List<Asset> assetResult = [SELECT Id FROM Asset where CreatedById=:userList[0].Id];
    delete assetResult;
    List<Case> caseResult = [SELECT Id FROM Case where CreatedById=:userList[0].Id];
    delete caseResult;
    List<Opportunity> oppResult = [SELECT Id FROM Opportunity where CreatedById=:userList[0].Id];
    delete oppResult;
    List<Contact> contResult = [SELECT Id FROM Contact where CreatedById=:userList[0].Id];
    delete contResult;
    List<Account> acctResult = [SELECT Id FROM Account where CreatedById=:userList[0].Id];
    delete acctResult;
}
```

### How Does Seeding Secure Data?

Seeding offers options to:

* Anonymize data, which replaces all potential Personally Identifiable Information (PII) with mock data.
* Pick objects in the hierarchy to skip
* Override fields with default values

These options help you make sure no sensitive production data ends up in a sandbox.

### How Does Seeding Handle Schema Mismatches?

Seeding assumes that the sandbox and production schemas match, as they do with the standard Salesforce Sandbox Refresh tooling.

However Seeding uses the same foundation as GRAX Restore, and contains a lot of smarts about schema mismatches. If a field doesn't exist in the sandbox schema, seeding will not include it. If an extra field exists, seeding will use the default or empty value, as well as let you override the field with a custom value.

## Feedback

GRAX regularly schedules meetings with customer teams to capture input on functionality and features. Please send all comments, feedback, and refinements to GRAX Customer Success.

## Troubleshooting

### Linking Seeded Records to Existing Users

If Seeded records are unexpectedly linked to the GRAX Integration User instead of other Salesforce users, check the following:

* Verify the GRAX Integration User has the "[Set Audit Fields upon Record Creation](https://help.salesforce.com/s/articleView?id=000386699\&type=1)" Salesforce permission in the Seeding Target Organization. This will allow audit fields like `CreatedBy, Owner, LastmodifiedBy` to be set when seeding records
* The User must exists in the Target Organization. GRAX Does not Seed Users for security purposes, instead we link users in both Organization based on the Full Name (`Name`) and Email Address (`Email`) values.
  * If we can't match the User, any required user fields will default to the GRAX Integration User when the record is created
  * Review the `User` object Details in the Seeding job Preview / Results to see more information on what User records were linked or skipped

### Salesforce Errors

Due to the complexity of Salesforce, you will sometimes experience errors when Seeding that require your intervention to get 100% of the records to seed. Some of these errors can be resolved by skipping objects, overriding fields, or adding relationships but sometimes they are purely due to Salesforce API rules. Causes may include triggers, permissions, or old data and such issues will be prefixed by 'Salesforce error:'. A partial list of these errors with suggested resolutions can be found [here](/other/troubleshooting). There is typically some back and forth to fully satisfy Salesforce rules, but with normal usage, troubleshooting becomes easier. GRAX also logs each error in our systems to help you debug.

If you need additional assistance contact [GRAX Support](/support/get-support).


# Sandbox Seeding Quickstart Guide

This guide walks you through your first Sandbox Seed in 10 minutes. This walk through is also available as a [Seeding Product Demo Video](https://www.grax.com/start/salesforce-sandbox-seeding/)

## Prerequisites

You'll need two Salesforce orgs and one GRAX deployment with full Backup.

* `Source` production SFDC org with:
  * Data in SFDC such as many Accounts hierarchies to see
  * A report in SFDC such as `GRAX Training Accounts` that finds all accounts that have `Training` in the name
* GRAX Application with full Backups of the `Source` org
* `Target` sandbox or production SFDC org with:
  * Schema matching the `Source` org, but no data as made by SFDC sandbox refresh tooling

Here we will use:

1. [Source "Test Drive" org](https://grax-trial.lightning.force.com) which you can [log into the Test Drive org through the Salesforce App Exchange](https://appexchange.salesforce.com/appxListingDetail?listingId=a0N3A00000FMtthUAD)
2. GRAX `Test Drive` App which you can [log into with a quick link](https://grax-trial-testdrive.us-east-1.jgaskagraxcom.dev.graxaws.com/web/seed?graxInternalSessionToken=uWVw5L4feZ.Bg91Hu8j0BQMWpkneRaxlKmiKKEMnSxwTB)
3. [Target "Demo Restore" org](https://graxsalesrestore.lightning.force.com/)

## Log into the Source Org

First [log into the Source org](https://appexchange.salesforce.com/appxListingDetail?listingId=a0N3A00000FMtthUAD).

Next [log into the GRAX Application](https://grax-trial-testdrive.us-east-1.jgaskagraxcom.dev.graxaws.com/web/seed?graxInternalSessionToken=uWVw5L4feZ.Bg91Hu8j0BQMWpkneRaxlKmiKKEMnSxwTB).

GRAX has a `Sandbox Seeding User` permission to grant access to perform search and seeding operations, but not access to settings, archive tooling, etc.

## Pick a Seed Target

Now go to [New Sandbox Seeding](https://grax-trial-testdrive.us-east-1.jgaskagraxcom.dev.graxaws.com/web/seed/new?graxInternalSessionToken=uWVw5L4feZ.Bg91Hu8j0BQMWpkneRaxlKmiKKEMnSxwTB) and configure a Target org. Either add a Target org by connecting via OAuth, or reuse an existing one.

Here we have a Demo Restore org pre-configured as a target.

## Pick a Seed Source

Next configure the data you'd like to see.

Here we will seed from a Salesforce report. In Salesforce, create a report with data you'd like to seed. For example this [GRAX Training Accounts Report](https://grax-trial.lightning.force.com/lightning/r/Report/00O8V000008SiPwUAK/view?queryScope=userFolders) with all Accounts that have "Training" in the name. All reports with `GRAX` in the name or in a `GRAX` folder show up in the GRAX Application.

Then in the GRAX seeding source tool select the Report option and select the Training Accounts Report.

## Preview and Run the Seed

Now click through the seeding tool to preview the data hierarchy, record count. Here we see the report includes 3 Accounts and 100s of child Assets, Contacts, Cases, etc.

Continue to click through to execute the seed. After a final confirmation the seeding activity will start and show all the progress, success, or errors.

## Review Seed Data

Finally if you log into [Target "Demo Restore" org](https://graxsalesrestore.lightning.force.com/) you'll see all the data.

With a few clicks we've taken data from one Salesforce org to another, giving your development team a good dataset in a sandbox to work against.


# Public API

GRAX's public API documentation is available [here](https://api.grax.com/); a private version is available on your own GRAX deployment under `/scalar` (for example `https://my-deployment-02.secure.grax.io/scalar`).

The OpenAPI specification is at the `/api/spec/grax.json` endpoint, for example `https://my-deployment-02.secure.grax.io/api/spec/grax.json`.

GRAX API tokens are created in the GRAX Application's `Settings` page. Under `API Tokens`. Admin users can create new tokens with scopes like:

* GRAX Admin
* Power User
* Purge User
* Sandbox Seeding User

For security reasons you can not access the plain text token after initial creation. Instead, you can only generate a new token and revoke old ones.

Some fundamental API troubleshooting steps are described below. Please exhaust these steps before contacting GRAX Support. Details about API support requests can be found at the bottom.

## My API request returned a 401 status code

A 401 status code indicates that the API request was incorrectly authenticated. This can happen for a number of reasons:

1. The API token was not included in the request
2. The headers used for API tokens are incorrect/mistyped
3. The API token is incorrect

The GRAX API tokens are available in the GRAX Application's `Settings` page. Under `API Tokens`. They should be placed in request headers, like:

```
Authorization: Bearer <API TOKEN>
```

## My failing API request includes parameter references

Make sure that any response being sent has correctly replaced any parameter references such as `{{org_id}}` that may have been included in documentation. Copying variable references that are not replaced is a common mistake.

## Getting Help with the API

{% hint style="danger" %}
**Do Not Transmit Secrets**

GRAX Support does not require the specific secret values of your API tokens to assist with troubleshooting. Please do not transmit these values to GRAX Support. Redact such values in place whenever sending request/response examples.
{% endhint %}

If none of the above steps have resolved the issue, please [contact GRAX Support](/support/get-support) and include the following information:

1. What client is being used? (Salesforce Apex, Postman, Python, Go, etc.)
2. What is the entire request being sent? (Method, URL, Body, Headers, etc.)
3. What is the entire response being received? (Status Code, Body, Headers, Duration, etc.)
4. What was the expected response?
5. A screenshot of the client sending the request and surrounding context (request construction, configuration, etc.)
6. The URL of the GRAX environment being targeted


# Managed Package

Work with your data from within Salesforce, without it being there

The GRAX Managed Package is a no-cost add-on to existing GRAX applications that allows customers to interact with GRAX data as part of their standard Salesforce experience. This includes archived and deleted records as well as past versions of live records. Additionally, users can interact with Global Search via a Tab inside Salesforce instead of leaving the platform to find data from backups.

For more information about the supported second-generation Managed Package, see:

{% content-ref url="/pages/1r0tnpZ7aF4Ay5n16mnv" %}
[Second Generation](/reuse-data/managed-package/second-generation)
{% endcontent-ref %}

For more information about the deprecated and unmaintained first-generation Managed Package, see:

{% content-ref url="/pages/xizoh4l5IXmz27bX4HD4" %}
[First Generation](/reuse-data/managed-package/first-generation)
{% endcontent-ref %}


# Second Generation

Currently Supported

The second-generation GRAX Managed Package is a ground-up re-imagination of exposing GRAX features natively within Salesforce. This package takes advantage of the [latest Salesforce package tools](https://developer.salesforce.com/docs/atlas.en-us.pkg2_dev.meta/pkg2_dev/sfdx_dev_dev2gp.htm), significantly reduces the amount of custom code added to your org (versus the first-generation package), eliminates the storage of secrets within Salesforce, and makes it easier to get GRAX in front of your users as fast as possible.

## App Exchange

This Managed Package has been reviewed and approved by Salesforce and is available via the Salesforce AppExchange:

{% embed url="<https://appexchange.salesforce.com/appxListingDetail?listingId=0416354a-cd03-4b68-912c-fb8aa382ac8d>" %}

## More Information

{% content-ref url="/pages/TW4l1Slxe4xWe7C0AxFS" %}
[Features](/reuse-data/managed-package/second-generation/features)
{% endcontent-ref %}

{% content-ref url="/pages/Rm3zCnCwPQbBC5m4sQxi" %}
[Install](/reuse-data/managed-package/second-generation/install)
{% endcontent-ref %}

{% content-ref url="/pages/Jq4JAkSRHali2QGFLOvT" %}
[Update](/reuse-data/managed-package/second-generation/update)
{% endcontent-ref %}

{% content-ref url="/pages/SWabsEoryGb41lD2UQb8" %}
[Uninstall](/reuse-data/managed-package/second-generation/uninstall)
{% endcontent-ref %}


# Features

Second-Generation Managed Package

{% hint style="success" %}

## Demos and Training Always Available

If you are a current or prospective customer of GRAX and interested in the Managed Package, our team is always happy to provide demonstrations, training, and/or installation assistance. Just [reach out to our Support team](/support/get-support) and they'll put you in touch with the right people.
{% endhint %}

{% hint style="danger" %}
These components are only available for the Lightning Experience on the Desktop. Salesforce Classic and mobile are not supported.
{% endhint %}

## Related Records Component

The Related Records component is designed to make viewing records that are related to a live Salesforce record as easy as possible, regardless of whether they are also live in Salesforce, were deleted by a user, or archived by GRAX.

<figure><img src="/files/HyefAcN09r13G7jw60p3" alt=""><figcaption><p>Related Records Component</p></figcaption></figure>

This component is most valuable in Salesforce orgs that take advantage of GRAX's Archive features to keep the size and growth of their org under control. As you move more of your historical data out of Salesforce, it becomes increasingly important to be able to access that data in a user friendly way. With this component, users don't even need to leave the record page to:

* See all cases ever opened for a customer, deleted or not
* Review email threads related to deleted cases
* Reread the notes on recurring tasks that were cleaned up years ago
* ...and much more.

This component can be placed on record detail pages. It automatically searches for records matching the configured filters that are related to the record being viewed. For example, if the component is placed on an Account record page, the component will display records related to that account or its children. The set of fields returned can be configured in the component settings once added to a page.

Users can jump out into the standalone GRAX web application at will if their exploration becomes deep or complicated enough by clicking on the record hyperlinks.

<details>

<summary>Configuration</summary>

The following settings can be configured via the component properties within the Lightning App Builder:

<table><thead><tr><th width="183">Setting</th><th>Effect</th></tr></thead><tbody><tr><td>Related Object</td><td>Controls the type of records that will be displayed.</td></tr><tr><td>Dataset Selection</td><td><p>Filters out records based on their deletion status.</p><p>Possible values are:</p><ul><li>All (Live, Deleted, and Archived records)</li><li>Archived (Deleted by GRAX Archive)</li><li>Deleted (Deleted by any other means)</li><li>Archived or Deleted (Anything not Live)</li></ul></td></tr><tr><td>Child Level</td><td><p>The level in the hierarchy under the root record that records should be retrieved from.</p><p>For example:</p><ul><li>1 means immediate children of the root record</li><li>2 means grandchildren of the root record</li><li>3 means children of grandchildren of the root record</li></ul></td></tr><tr><td>Fields</td><td>A comma-separated list of Field API names to include in the output table. If no field exists for a provided name, that column will be blank in the resulting table.</td></tr><tr><td>Records Per Page</td><td>The number of records that will be displayed at once on the table. If more records than this exist, users can page through the results.</td></tr><tr><td>Override Title</td><td>Allows customization of the default page title which is usually based on the root object type.</td></tr><tr><td>Height</td><td>Sets the height of the component in the page.</td></tr><tr><td>Additional Configuration</td><td>A place to set optional, advanced configuration values that get passed to the GRAX application.</td></tr></tbody></table>

</details>

## Record Versions Component

The Record Versions component is designed to make exploration of single-record history as easy as possible. This component can be placed on record detail pages. All backed up versions of the target record will be shown in the table, alongside a measure of how different each version is from the current state of the record.

<figure><img src="/files/Xzvr1viyDJfJWlENtRoA" alt=""><figcaption><p>Record Versions Component</p></figcaption></figure>

Through use of the "Compare" functionality, users can see at a granular level what was changed in each version, what the old and new values were at each change, and even who made the change. Users can restore either an entire version of a record or cherry-pick specific fields from specific versions to restore.

<figure><img src="/files/8zqo9XKyqLjfqKrLvtG6" alt=""><figcaption><p>Record Versions Comparison</p></figcaption></figure>

Users can jump out into the standalone GRAX web application at will if their exploration becomes deep or complicated enough by clicking on the record name hyperlink.

<details>

<summary>Configuration</summary>

The following settings can be configured via the component properties within the Lightning App Builder:

| Setting          | Effect                                                                                                                                  |
| ---------------- | --------------------------------------------------------------------------------------------------------------------------------------- |
| Records Per Page | The number of records that will be displayed at once on the table. If more records than this exist, users can page through the results. |
| Override Title   | Allows customization of the default page title which is usually based on the root object type.                                          |
| Height           | Sets the height of the component in the page.                                                                                           |

</details>

### Previewing the LWC in your GRAX App

The Related Record Builder within your GRAX app provides an interactive tool to build and preview the LWC configuration. Simply navigate to your GRAX App Settings, click on Diagnostics and Tools and choose the Related Record Builder at the bottom of the page.

<figure><img src="/files/8tU235Qs2k4c3sxY40LG" alt=""><figcaption><p>Related Record Builder Sample Data</p></figcaption></figure>

#### Configuring the Related Record Builder

* Under General Settings, enter in the Parent Record ID of the object you'd like to view.
* Enter an Override Title (e.g., 'Archived Case Records')*.*
* Choose the Related Object you want to display (e.g., 'Case').
  * When the Related Object is chosen the Child Level will automatically populate with the correct level of the Related Object.
* Select the Data Set Selection: All Data, Archived Data, Deleted Data, or Archived + Deleted Data.
* Add the Fields you want to display on the LWC (e.g., Case Number, Subject, Status).

By default, the Sample Data will show the record ID, mod stamp and the "Name" field. However, once you specify the fields you'd like to display those are dropped for your selection.

<figure><img src="/files/otbXV6KVeu9DP1NsGG9e" alt=""><figcaption><p>Related Record Builder General Settings</p></figcaption></figure>

Once the LWC preview is configured to your liking, use the LWC Settings Reference to auto-populate your settings within the Salesforce LWC directly. Click the Copy to LWC button (box with arrow icon) to transfer your settings.

<figure><img src="/files/bxo5PR4Vg7IVNVcFbXdl" alt=""><figcaption><p>LWC Settings Reference</p></figcaption></figure>

## Global Search Component

The Global Search component is designed to let users search for data within GRAX using powerful filters and conditions without needing to leave the Salesforce platform. It offers parity with the normal Global Search experience in a form that will sit right alongside your other application tabs in Salesforce.

<figure><img src="/files/3D9EBYiKB4lU4pI2Fn3D" alt=""><figcaption><p>Global Search Custom Tab</p></figcaption></figure>

As an Administrator, you can let your users interact with the full Global Search feature set, shown above, or give users a constrained template-based experience, shown below. Templates allow Administrators to define performant, index-optimized searches for use by end-users. This can help reduce the wait-time for results, strain on infrastructure, and the amount of training required for new users.

<figure><img src="/files/6AJVbIhYdJ99pnVd51pE" alt=""><figcaption><p>Template Search in Search Tab Component</p></figcaption></figure>

<figure><img src="/files/VmiyHN1A2pBtocIqMLb1" alt=""><figcaption><p>Template Search Results</p></figcaption></figure>

<figure><img src="/files/WbcLrlBDSmRyCFuwpbVx" alt=""><figcaption><p>Template Search Record View</p></figcaption></figure>

<details>

<summary>Configuration (App or Home Page)</summary>

This configuration information is only relevant if using the Search component on an "AppPage" or "HomePage" within Salesforce. If using the component as a standalone Custom Tab, see the section below.

| Setting          | Effect                                                                                                                                                                                                                                                                           |
| ---------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Mode             | <p>If "Full Search" is selected, users will see the full Global Search experience.<br><br>If "Template Search" is selected, users will see the template-based Search experience.</p>                                                                                             |
| Show Template ID | <p><em>This setting only has an effect if the "Mode" setting is set to "Template Search".</em><br><br>If enabled, users will be shown the input form for a specific template with the given ID.<br><br>If disabled, users will be shown the list of all available templates.</p> |

</details>

<details>

<summary>Configuration (Custom Tab)</summary>

This configuration information is only relevant if using the Search component on a standalone Custom Tab within Salesforce. If using the component on an App or Home page within Salesforce, see the section above.

Custom Tabs within Salesforce do not have the same configuration options as native Lightning Web Components. To change the behavior of your Custom Tab, you can change settings within the GRAX package's Custom Settings:

| Setting                      | Effect                                                                                                                                                                                                                                                                                 |
| ---------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Search Tab: Template Search  | <p>If enabled, users will see the template-based Search experience within the Custom Tab.</p><p>If disabled, users will see the full Global Search experience within the Custom Tab.</p>                                                                                               |
| Search Tab: Show Template ID | <p><em>This setting only has an effect if the "Search Tab: Template Search" setting is enabled.</em><br><br>If enabled, users will be shown the input form for a specific template with the given ID.<br><br>If disabled, users will be shown the list of all available templates.</p> |

*These settings do not have any impact on the Search component when used as a native Lightning Web Component on an App or Home page.*

</details>

{% hint style="success" %}

## Do you need something slightly different?

We're always looking for feedback on the user experience and feature set of our Lightning Web Components. If you have a specific use case that isn't covered by the components above, please [open a support ticket](/support/get-support) to discuss your needs.
{% endhint %}

## Permissions Model

The components included in the Managed Package are secured by the same permissions model that the normal GRAX application interface uses. To use the components, users must have one of the following permission sets:

* GRAX Console Standard Permission
* GRAX Console Seeding Permission
* GRAX Console Purge Permission
* GRAX Console Power Permission
* GRAX Console Admin Permission

These permission sets are created by Auto Config when you connect your GRAX app for the first time.

Users will also need to self-authorize the GRAX connected app by opening the GRAX application in a separate tab the first time they log in. This can be avoided by an admin pre-authorizing the users via the Connected App settings.


# Install

Second-Generation Managed Package

{% hint style="warning" %}

#### GRAX Application Required

The GRAX Managed Package consists of Lightning Web Components that send traffic to a GRAX application server in order to function. Make sure you have a healthy GRAX app running with Backup enabled before setting up the Managed Package.
{% endhint %}

Installing and configuring the second-generation Managed Package for the first time is quick and easy. The steps below cover everything from choosing the right org to getting a component added to your first page layout. If you become stuck or encounter unexpected issues while following these steps, feel free to [contact our Support team](/support/get-support) for assistance.

{% stepper %}
{% step %}

### Choosing the Right Salesforce Org

The Managed Package needs to be installed into the same Salesforce org that the GRAX application you'll be using is connected to. Make sure you're using that org for this process.
{% endstep %}

{% step %}

### Log in to Salesforce

Log in to the chosen Salesforce org via your standard login process as a user with the permissions to install Managed Packages. The standard "System Admin" profile is sufficient.
{% endstep %}

{% step %}

### Start the Installation

Depending on the type of org you've chosen, open the relevant link below to start the install process.

{% tabs %}
{% tab title="Production Orgs" %}
Use this link for any Salesforce org that is considered a production org or which uses the `login.salesforce.com` login page (like Developer Edition orgs).

{% embed url="<https://getgrax.co/prod-gen2>" %}
{% endtab %}

{% tab title="Sandbox Orgs" %}
Use this link for any Salesforce org that is considered a sandbox or which uses the `test.salesforce.com` login page.

{% embed url="<https://getgrax.co/sandbox-gen2>" %}
{% endtab %}
{% endtabs %}

Opening the correct link will cause a package installation menu to appear.

Salesforce allows packages to be installed for all or some of your users and will present you with a few options. These options determine which users are granted access to the components and classes that power the package features. These options, and their impact, break down as follows:

{% tabs %}
{% tab title="Install for Admins Only" %}
Specifies the following settings on the installing administrator’s profile and any profile with the `Customize Application` permission:

* Apex classes - enabled
* Custom LWC tab - enabled
* Custom Settings record - enabled
* Second Generation LWCs - enabled

After installation, if you have Enterprise, Performance, Unlimited, or Developer Edition, set the appropriate user and object permissions on custom profiles as needed
{% endtab %}

{% tab title="Install for All Users" %}
Specifies the following settings on all internal custom profiles:

* Apex classes - enabled
* Custom LWC tab - enabled
* Custom Settings record - enabled
* Second Generation LWCs - enabled
  {% endtab %}

{% tab title="Install for Specific Profiles" %}
Enables you to choose the usage access for all custom profiles in your organization. You can set each profile to have full access or no access for the new package and all its components.

* Full Access
  * Apex classes - enabled
  * Custom LWC tab - enabled
  * Custom Settings record - enabled
  * Second Generation LWCs - enabled
* No Access
  * Apex classes - disabled
  * Custom LWC tab - disabled
  * Custom Settings record - disabled
  * Second Generation LWCs - disabled
    {% endtab %}
    {% endtabs %}

Select the group you would like to install the package for and click "Install."

Please note that only power and admin users can see and use the restore button on the LWC.

<figure><img src="/files/31QoMtdMtyeqr1FY7Ueu" alt=""><figcaption><p>Installing for All Users</p></figcaption></figure>

Installation should take less than a minute in an average org, but may take longer if you have a very large or very customized org. During the wait, you will see a loading indicator.

<figure><img src="/files/1HQPgptOFwoACOXPAfRp" alt=""><figcaption><p>Waiting/Loading Message</p></figcaption></figure>

Once the installation is completed, a success message will show and you will receive a confirmation email.

<figure><img src="/files/IAEYtGT0LvR36NjfXJzZ" alt=""><figcaption><p>Success Message</p></figcaption></figure>

<figure><img src="/files/so57iEoO8OPmnMS50JFt" alt=""><figcaption><p>Confirmation Email</p></figcaption></figure>

### Permissions Model <a href="#permissions-model" id="permissions-model"></a>

{% hint style="warning" %}
If the managed package was initially installed for Admins only, and access later needs to be granted to other profiles, certain components must be manually assigned to the appropriate user profiles in Salesforce.
{% endhint %}

The components included in the Managed Package are secured by the same permissions model that the normal GRAX application interface uses. To use the components, users must have one of the following permission sets:

* GRAX Console Standard Permission
* GRAX Console Seeding Permission
* GRAX Console Purge Permission
* GRAX Console Power Permission
* GRAX Console Admin Permission

These permission sets are created by Auto Config when you connect your GRAX app for the first time.

Users will also need to self-authorize the GRAX connected app by opening the GRAX application in a separate tab the first time they log in. This can be avoided by an admin pre-authorizing the users via the Manage Connected App settings.

#### Configure Permissions for Additional Users

* In Salesforce, go to `Settings` - Search for Installed Packages
* Locate the GRAX Lightning Web Components installed package
* Click `View Components`
* Click on the **`Versions`** Apex Class - click the `Security` button and add the user profiles as needed
* Repeat these steps for the **`CustomSettings`** Apex Class
* Additionally, assign the GRAX Search Tab to the desired Salesforce user apps.

OR alternatively,

* In Salesforce, go to `Settings` - Search for Manage Connected Apps
* Locate and Edit GRAX Oauth
* Adjust Permitted users to 'Admin approved users are pre-authorized'
* Click Save
* Scroll down to locate Profiles and click Manage Profiles
* Select the profiles you desire to have access to the GRAX LWC
  {% endstep %}

{% step %}

### Configure Custom Settings

The components included in the package source the target server URL from a Custom Setting. Installing the package creates this custom setting, but it is empty by default. You will need to set an organization-default value for the setting before anyone can use the components.

Start by opening the custom settings menu.

<figure><img src="/files/vNdnniasQGUE6n01crLg" alt=""><figcaption></figcaption></figure>

Find the "GRAX Settings" item in the list and click "Manage."

<figure><img src="/files/1YeCGtJw5V0U3jsm7sJ0" alt=""><figcaption></figcaption></figure>

Click "New" to create a new organization-level default setting.

<figure><img src="/files/hjNQys8Z3Rru3CMxRuWc" alt=""><figcaption></figcaption></figure>

Enter the full `https://[...].com` formatted public domain name of your GRAX application without a trailing slash and click "Save."

<figure><img src="/files/Gbbwi4TNYXahJlcDMDVH" alt=""><figcaption></figcaption></figure>
{% endstep %}

{% step %}

### Configure a Trusted URL (Application)

The components included in the package are iframed pages retrieved from your GRAX application server. Due to browser security restrictions, additional configuration is necessary to tell Salesforce that you trust the GRAX server to serve iframe content in your org.

To start, open the "Trusted URLs" menu.

<figure><img src="/files/V72U3LhFA05IAPaf9YWz" alt=""><figcaption></figcaption></figure>

To add a new Trusted URL for your GRAX application, click "New Trusted URL."

<figure><img src="/files/NKv5PNtxuZ6AwDbFP2XD" alt=""><figcaption></figcaption></figure>

Make the following changes to the "New Trusted URL" form:

* Name it anything you'd like
* Use the same `https://[...].com` formatted domain name as used in the Custom Setting as the URL
* Check the `frame-src` box
* Leave the `img-src` box checked

Now click "Save" to create the record.

<figure><img src="/files/LG9uQOzNS30KSg9JQwZt" alt=""><figcaption></figcaption></figure>
{% endstep %}

{% step %}

### Configure Another Trusted URL (HQ)

Due to enhanced default Content Security Policy settings in recent Salesforce releases, it's necessary to also flag GRAX's centralized authentication server as trusted. Repeat the steps above to create another Trusted URL, but make the following modifications to the form:

* Name it anything you'd like
* Use `https://hq.grax.com` as the URL
* Check the `frame-src` box
* Leave the `img-src` box checked

Now click "Save" to create the record.
{% endstep %}

{% step %}

### Add a Component to a Page Layout

To see a component in action and test it out, you'll need to modify a page layout for a standard object. Start by opening a standard object record (Case, for example) page in your Salesforce org and then opening the "Setup" sidebar. Click the "Edit \[Object] Page" option under "Customization" to open the Lightning App Builder.

<figure><img src="/files/zeTz9O3vcHFpyqjSX02I" alt=""><figcaption></figcaption></figure>

Within the Lightning App Builder, the record-page-compatible GRAX components will be available under the "Custom - Managed" category in the components list.

<figure><img src="/files/T6ocAO0TNqjdwosVLv1j" alt=""><figcaption></figcaption></figure>

{% hint style="warning" %}
It is recommended to place GRAX components on a separate tab that is not loaded by default when a user opens the record page. This improves the load time of the page in common use cases and minimizes unnecessary traffic to and from your GRAX application.
{% endhint %}

For purposes of initial testing, we'll use the Related Records component. To add a component to the page, create a new tab and drag the GRAX component onto it from the "components" menu. Initially, some components (like Related Records) may have invalid configurations because they need additional setup to behave properly.

<figure><img src="/files/R4JItUkqV4Txk2CSIplg" alt=""><figcaption></figcaption></figure>

Add the API name of any object directly related to the parent object (whatever object's record page you're modifying) to the component's input settings and save the layout.

<figure><img src="/files/AP2pt5uJuUJAqJPpwBKH" alt=""><figcaption></figcaption></figure>

The component should now render with data based on your backed up data. Depending on exactly which objects you chose, the exact format of the component may vary. A few examples of the Related Records component are shown below for reference.

<figure><img src="/files/EcpTJk5RXRgb5Ffk7avy" alt=""><figcaption></figcaption></figure>

<figure><img src="/files/HyefAcN09r13G7jw60p3" alt=""><figcaption></figcaption></figure>

Initial setup and verification is now complete. For more information about the package, checkout our [feature](/reuse-data/managed-package/second-generation/features), [update](/reuse-data/managed-package/second-generation/update), and [uninstall](/reuse-data/managed-package/second-generation/uninstall) guides.
{% endstep %}

{% step %}

### Frequently Asked Questions

#### Why am I seeing an unable to connect error on the LWC?

If the integration user and power users or admin users are seeing this message then the required permission sets are not created.

To resolve this, log out of both GRAX and Salesforce. Log into GRAX via the SSO option to self-authorize.

Log back into Salesforce and the LWC will be able to be viewed.
{% endstep %}
{% endstepper %}


# Update

Second-Generation Managed Package

Updates to the second-generation Managed Package will occasionally be released in order to introduce new components or resolve issues present in prior versions. Release notes for Managed Package versions are available in the [Notices](https://documentation.grax.com/notices/) section. Updates are simple and quick to install and usually do not require any configuration changes.

The steps below walk through the typical update process. If you become stuck or encounter unexpected issues while following these steps, feel free to [contact our Support team](/support/get-support) for assistance.

{% stepper %}
{% step %}

### Log in to Salesforce

Log in to your Salesforce org via your standard login process as a user with the permissions to update Managed Packages. The standard "System Admin" profile is sufficient.
{% endstep %}

{% step %}

### Start the Update

Depending on the type of org you've chosen, open the relevant link below to start the update process.

{% tabs %}
{% tab title="Production Orgs" %}
Use this link for any Salesforce org that is considered a production org or which uses the `login.salesforce.com` login page (like Developer Edition orgs).

{% embed url="<https://getgrax.co/prod-gen2>" %}
{% endtab %}

{% tab title="Sandbox Orgs" %}
Use this link for any Salesforce org that is considered a sandbox or which uses the `test.salesforce.com` login page.

{% embed url="<https://getgrax.co/sandbox-gen2>" %}
{% endtab %}
{% endtabs %}

Opening the correct link will cause a package update menu to appear.

Salesforce allows packages to be installed for all or some of your users and will present you with a few options. These options determine which users are granted access to the components and classes that power the package features. These options, and their impact, break down as follows:

{% tabs %}
{% tab title="Install for Admins Only" %}
Specifies the following settings on the installing administrator’s profile and any profile with the `Customize Application` permission:

* Apex classes - enabled
* Custom LWC tab - enabled
* Custom Settings record - enabled
* Second Generation LWCs - enabled

After installation, if you have Enterprise, Performance, Unlimited, or Developer Edition, set the appropriate user and object permissions on custom profiles as needed
{% endtab %}

{% tab title="Install for All Users" %}
Specifies the following settings on all internal custom profiles:

* Apex classes - enabled
* Custom LWC tab - enabled
* Custom Settings record - enabled
* Second Generation LWCs - enabled
  {% endtab %}

{% tab title="Install for Specific Profiles" %}
Enables you to choose the usage access for all custom profiles in your organization. You can set each profile to have full access or no access for the new package and all its components.

* Full Access
  * Apex classes - enabled
  * Custom LWC tab - enabled
  * Custom Settings record - enabled
  * Second Generation LWCs - enabled
* No Access
  * Apex classes - disabled
  * Custom LWC tab - disabled
  * Custom Settings record - disabled
  * Second Generation LWCs - disabled
    {% endtab %}
    {% endtabs %}

Select the group you would like to install the package for and click "Install."

<figure><img src="/files/EXMy51qaGhCoITTMwIR8" alt=""><figcaption></figcaption></figure>

Updating should take less than a minute in an average org, but may take longer if you have a very large or very customized org. During the wait, you will see a loading indicator. Once complete, you will receive a confirmation email.
{% endstep %}

{% step %}

### Validate the Components

To be safe, it is best to validate that your existing components still work after the update. Visit pages that contain each unique component and verify that each component is functioning correctly still to make sure that no issues surprise you or your users later.
{% endstep %}
{% endstepper %}


# Uninstall

Second-Generation Managed Package

{% hint style="danger" %}

#### User Impact

Before uninstalling any Managed Package, always make sure that your business and users are not actively depending on it. Uninstalling a package requires removing all components, custom code, and custom objects associated with that package. Proceed at your own risk.
{% endhint %}

If it becomes necessary to remove the second-generation Managed Package from your Salesforce org, manual effort may be required. Due to the customization that happens after a package is installed (like adding components to page layouts), it's almost always more difficult to unwind and uninstall a package than add one.

The steps below walk through the process of uninstalling this package. If you become stuck or encounter unexpected issues while following these steps, feel free to [contact our Support team](/support/get-support) for assistance.

{% stepper %}
{% step %}

### Log in to Salesforce

Log in to your Salesforce org via your standard login process as a user with the permissions to uninstall Managed Packages. The standard "System Admin" profile is sufficient.
{% endstep %}

{% step %}

### Try Uninstalling the Package

Open the "Setup" menu, then open "Installed Packages" via the Quickfind search.

<figure><img src="/files/ULyelRJ91OAjxbk0HING" alt=""><figcaption></figcaption></figure>

Find "GRAX Lightning Web Components" in the packages list, and click "Uninstall."

<figure><img src="/files/gufpihZZaNRqKpGhMkpQ" alt=""><figcaption></figcaption></figure>

Check the confirmation checkbox on the next page, and click "Uninstall."

<figure><img src="/files/qJ3Chu80ilXfayRsbLtU" alt=""><figcaption></figcaption></figure>

If the uninstall is successful, you will receive a confirmation email. If you receive this email, you are done with this guide and do not need to continue reading. If your uninstall failed, keep reading.

<figure><img src="/files/GLcvjZN75veEUFjps3Rf" alt=""><figcaption></figcaption></figure>

On the first attempt, it is likely that you will receive errors about components or other resources in the package still being used somewhere. Usually, these just mean that you have page layouts that still contain the component. The error page should list the page layouts and resources impacted.

<figure><img src="/files/zPjxnwjCFvZPYQwUTPZ8" alt=""><figcaption></figcaption></figure>

It is your responsibility to update these page layouts to no longer include the GRAX components (or otherwise resolve any errors during installation). Do your best to resolve all possible issues, then continue.
{% endstep %}

{% step %}

### Try Uninstalling the Package Again

Now that you've resolved all possible issues that appeared during the previous attempt, try uninstalling the package again using the original steps.

If you encounter more issues, resolve them and repeat this process until the uninstall is successful. If you come across a reported issue that you cannot resolve, feel free to [reach out to our Support team](/support/get-support) for assistance.
{% endstep %}
{% endstepper %}


# First Generation

{% hint style="danger" %}
The First Generation Managed Package is being deprecated in favor of the newer, more advanced [Second Generation Managed Package](https://documentation.grax.com/reuse-data/managed-package/second-generation).

For additional details, please see our retirement notice [here](https://documentation.grax.com/notices/feature-retirements/first-generation-managed-package-retirement).
{% endhint %}

The first-generation GRAX Managed Package is a deprecated implementation of the core GRAX product as well as the Lightning Web Components. This package includes a large amount of custom code, custom objects, triggers, a managed application, a dozen permission sets, protected custom settings, and several scheduled jobs. It is more complicated to set up and maintain than the second-generation package and no longer receives updates.

## Installing or Updating

If you are an existing user of the first-generation package and need to install it into another org or patch an older version version of the package in your org, please [reach out to our Support team](/support/get-support) for help.

## More Information

{% content-ref url="/pages/1EjUBgfycjSfFa3V6F7C" %}
[Features](/reuse-data/managed-package/first-generation/features)
{% endcontent-ref %}

{% content-ref url="/pages/3nnQIGXHHYvyEkX994OG" %}
[Uninstall](/reuse-data/managed-package/first-generation/uninstall)
{% endcontent-ref %}

{% content-ref url="/pages/3MYkhXsuTQP4Mas5fmoV" %}
[Migrate](/reuse-data/managed-package/first-generation/migrate)
{% endcontent-ref %}


# Features

First-Generation Managed Package (Deprecated)

{% hint style="danger" %}
These components are deprecated. The components in the [Second Generation](/reuse-data/managed-package/second-generation) Managed Package are the functional replacements.
{% endhint %}

{% hint style="warning" %}
This document omits the sections of the first-generation package that are entirely defunct like Legacy Backup, Legacy Archive, and Legacy Restore. That functionality has been rolled into the standard GRAX application.
{% endhint %}

## List Records Component

The GRAX List Records component is purpose-built for use on a "record page" in Salesforce. It can be added to a record page layout and configured to display records for a specific object that is related to the current context. Records can be filtered by status (live, deleted, archived, etc.) and displayed fields can be specified per component instance.

Use cases include:

* Display archived and/or deleted Email Messages related to a Case
* Display all recent Cases for an Account, regardless of whether or not they have been deleted

<details>

<summary>Configuration</summary>

The following settings can be configured via the component properties within the Lightning App Builder:

| Setting               | Effect                                                                                                                                                                                                                                                                                                      |
| --------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Related Object        | Controls the type of records that will be displayed.                                                                                                                                                                                                                                                        |
| Related Object Fields | A comma-separated list of Field API names to include in the output table. If no field exists for a provided name, that column will be blank in the resulting table.                                                                                                                                         |
| Override Title        | Allows customization of the default page title which is usually based on the root object type.                                                                                                                                                                                                              |
| Data Set Selection    | <p>Filters out records based on their deletion status.</p><p>Possible values are:</p><ul><li>All Data (Live, Deleted, and Archived records)</li><li>Archived Data (Deleted by GRAX Archive)</li><li>Deleted Data (Deleted by any other means)</li><li>Archived + Deleted Data (Anything not Live)</li></ul> |
| Use iFrame            | If true, changes to the component to behave like the second-generation Related Records component minus some security improvements. Improves loading speed for results.                                                                                                                                      |
| iFrame px size        | Determines the size of the component when "Use iFrame" is enabled.                                                                                                                                                                                                                                          |
| Records Per Page      | The number of records that will be displayed at once on the table. If more records than this exist, users can page through the results.                                                                                                                                                                     |
| Hide ID Field         | If true, removes the record ID column from the results table.                                                                                                                                                                                                                                               |
| Child Level           | <p>The level in the hierarchy under the root record that records should be retrieved from.</p><p>For example:</p><ul><li>1 means immediate children of the root record</li><li>2 means grandchildren of the root record</li><li>3 means children of grandchildren of the root record</li></ul>              |
| Additional Parameters | A place to set optional, advanced configuration values that get passed to the GRAX application.                                                                                                                                                                                                             |
|                       |                                                                                                                                                                                                                                                                                                             |

The following settings are only applicable when the "Use iFrame" option is not enabled:

| Setting                                              | Effect                                                                                                                                                                                                                                                                                                                                |
| ---------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Hide Show Record                                     | Determines whether the "Show Record" option is visible in the drop-down menu located on the far right of each row within the component.                                                                                                                                                                                               |
| Hide Show in GRAX                                    | Determines whether the "Show in GRAX" option is visible in the drop-down menu located on the far right of each row within the component.                                                                                                                                                                                              |
| Hide View Graph                                      | Determines whether the "View Graph" option is visible at the top of the component and in the drop-down menu located on the far right of each row within the component.                                                                                                                                                                |
| Hide Restore Button                                  | Determines whether the "Restore" button is visible within the component after clicking "Show Record." This setting is only applicable if the "Hide Show Record" setting is disabled.                                                                                                                                                  |
| Do NOT Enforce Security or Salesforce Object Deleted | Determines whether the component respects Field Level Security. "Salesforce Object Deleted" is bundled with not enforcing Field Level Security because when an object is deleted, Salesforce does not contain that object schema anymore, and therefore GRAX cannot check if the component user should see the deleted object or not. |

</details>

## Versions Component

The GRAX Versions component is purpose-built for use on a "record page" in Salesforce as well. It can be add to a record page layout and configured to display all historical versions of the currently viewed record. This allows users to analyze changes to a record over time, identify who made changes, and even restore a previous version of the record if necessary.

This component has no configuration options.

## Single Record Restore Component

The Single Record Restore component provides restore capability to end users. While it's possible to install this component individually on a page, it does rely on the GRAX Versions component to provide the capabilities described here.

This component has no configuration options.

## Permissions Model

The first-generation Managed Package includes a number of permission sets, most of which are defunct at this time. To access the components described here, users must be assigned one of the following permission sets:

* GRAX - User
* GRAX - Advanced User
* GRAX - Configuration Admin

Users must also have access to the GRAXLWCHelper Apex class in order for the components to load. You can grant access to the GRAXLWCHelper Apex Class by navigating to the user's profile, clicking on "Enabled Apex Class Access", adding the GRAXLWCHelper Apex Class and then clicking "Save".

If "Use iFrame" is enabled for the List Records component, Users will also need to self-authorize the GRAX connected app by opening the GRAX application in a separate tab the first time they log in. This can be avoided by an admin pre-authorizing the users via the Connected App settings.


# Configure

First-Generation Managed Package (Deprecated)

Existing installations of the first-generation Managed Package may occasionally require reconfiguration based on sandbox refreshes or GRAX application migrations. The main forms of configuration are covered below.

## Trusted URLs

The components included in the package include remote callouts and iframed pages retrieved from your GRAX application server. Due to browser security restrictions, additional configuration is necessary to tell Salesforce that you trust the GRAX server to serve content in your org.

Open the "Trusted URLs" menu from the "Setup" menu, and create a new Trusted URL. Name it anything you'd like, and use the `https://[...].com` formatted domain name of your GRAX application as the URL value. Ensure the `frame-src` and `img-src` checkboxes are selected, and click "Save."

<figure><img src="/files/LG9uQOzNS30KSg9JQwZt" alt=""><figcaption></figcaption></figure>

Due to enhanced default Content Security Policy settings in recent Salesforce releases, it's necessary to also flag GRAX's centralized authentication server as trusted. Repeat the steps above to create another Trusted URL, but use `https://hq.grax.com` as the URL.

## GRAX API Tokens

Any time you change your GRAX application's URL or your application is migrated by GRAX, your package settings will need to be updated to point to the new location and use the right secrets.

To find the correct URL and token values for your application, open "Settings" and click "Reveal Legacy Tokens" under "API Tokens." From there, values can be copied into the package directly.

To expose the token form in the package, click "Unlock" in the bottom right of the main package page.

<figure><img src="/files/WfcpNwQm0JXh2IYpmOv8" alt=""><figcaption></figcaption></figure>

## Remote Site Setting

Due to Apex callouts within the first-generation package code, a Remote Site Setting must be created for your GRAX application domain. Clicking the "Add Remote Site Setting" on the main package page will auto-populate the form for adding a new setting, at which point you can hit save and refresh the package page.

<figure><img src="/files/6SubteGMEbYWpwRNQGOJ" alt=""><figcaption></figcaption></figure>


# Uninstall

First-Generation Managed Package (Deprecated)

{% hint style="danger" %}

## User Impact

Before uninstalling any Managed Package, always make sure that your business and users are not actively depending on it. Uninstalling a package requires removing all components, custom code, and custom objects associated with that package. Proceed at your own risk.
{% endhint %}

When you are ready to remove the first-generation package from your org, the steps below can help. If you become stuck or encounter unexpected issues while following these steps, feel free to [contact our Support team](/support/get-support) for assistance.

{% stepper %}
{% step %}

### Log in to Salesforce

Log in to your Salesforce org via your standard login process as a user with the permissions to uninstall Managed Packages. The standard "System Admin" profile is sufficient.
{% endstep %}

{% step %}

### Try Uninstalling the Package

Open the "Setup" menu, then open "Installed Packages" via the Quickfind search.

Find "GRAX" in the packages list, and click "Uninstall."

Check the confirmation checkbox on the next page, and click "Uninstall."

<figure><img src="/files/HrsXFjxzAhFHPXQt7KxG" alt=""><figcaption></figcaption></figure>

If the uninstall is successful, you will receive a confirmation email. If you receive this email, you are done with this guide and do not need to continue reading. If your uninstall failed, keep reading.

On the first attempt, it is likely that you will receive errors about components or other resources in the package still being used somewhere. A few common categories of these issues (and their solutions) are:

* Users still assigned permission sets
  * Remove the package permission sets (those that start with "GRAX - ") from all users
* Lightning Web Components still present in page layouts
  * Remove the components from the page layouts
* Apex classes still referenced in Scheduled Jobs
  * Delete the "GRAXScheduledWorker" jobs from your "Scheduled Apex Jobs" list

Try to fix as many of these issues as possible, then proceed.
{% endstep %}

{% step %}

### Try Uninstalling the Package Again

Now that you've resolved all possible issues that appeared during the previous attempt, try uninstalling the package again using the original steps.

If you encounter more issues, resolve them and repeat this process until the uninstall is successful. If you come across a reported issue that you cannot resolve, feel free to [reach out to our Support team](/support/get-support) for assistance.
{% endstep %}
{% endstepper %}


# Migrate

Updating to the Second-Generation Managed Package

{% hint style="warning" %}
You will need to [install](https://documentation.grax.com/reuse-data/managed-package/second-generation/install) the second-generation GRAX Managed Package, and [uninstall](https://documentation.grax.com/reuse-data/managed-package/first-generation/uninstall) the first-generation Managed Package during the migration process.
{% endhint %}

The primary blocker when switching between generations of the Managed Package is managing the access that users have to GRAX features and components. The first-generation package includes legacy permission sets that can be used to control user access, but the second-generation relies on permission sets created by the GRAX application during Auto Config. When removing the first-generation package, users assigned the legacy permission sets need to be updated to the equivalent set to avoid interruptions.

For more details on GRAX's permissions model, see our [Roles for End Users](/other/permissions-and-access/roles-for-end-users) documentation.

For migration purposes, the non-defunct legacy permission sets map as follows:

| Old Permission Set Name  | New Permission Set Name          |
| ------------------------ | -------------------------------- |
| GRAX Configuration Admin | GRAX Console Admin Permission    |
| GRAX Advanced User       | GRAX Console Power Permission    |
| GRAX User                | GRAX Console Standard Permission |

All other legacy permission sets have no equivalent and are defunct. They can be dropped from users without consequence.

### Automatically Migrating Permission Sets

The following steps and script can be used to automatically perform the mapping shown above for all users in your org.

{% stepper %}
{% step %}

### Open the Developer Console

Documentation on how to open the console is available [here](https://help.salesforce.com/s/articleView?id=platform.code_dev_console_opening.htm\&type=5).

Once the console is open, expand the "Debug" menu and click "Open Execute Anonymous Window."
{% endstep %}

{% step %}

### Run the Script

Copy the following script into the "Enter Apex Code" dialog box.

```apex
private class GRAXLegacyPerm {
  Map<String, Id> psIDs;
  Map<String, Set<Id>> existingConsole;

  public GRAXLegacyPerm() {
    List<PermissionSet>lps=[
        SELECT Id, Name
        FROM PermissionSet
        WHERE name in ('GRAX_Configuration_Admin', 'GRAX_Advanced_User', 'GRAX_User', 'GRAX_Console_Admin_User', 'GRAX_Console_Power_User', 'GRAX_Console_Standard_User')
    ];

    psIDs = new Map<String, Id>();
    for(PermissionSet ps : lps){
        System.debug('PermissionSet '+ps.Name +' Id: ' + ps.Id);
        psIDs.put(ps.Name, ps.Id);
    }

    existingConsole = new Map<String, Set<Id>>();
    for (String name : new String[]{'GRAX_Console_Admin_User', 'GRAX_Console_Power_User', 'GRAX_Console_Standard_User'}) {
         List<PermissionSetAssignment> ecpsa = [
            SELECT AssigneeId
            FROM PermissionSetAssignment
            WHERE IsActive=true
              AND PermissionSetId = :psIDs.get(name)
        ];

        Set<Id> ecpsuID = new Set<Id>();

        for (PermissionSetAssignment a : ecpsa) {
            ecpsuID.add(a.AssigneeId);
        }
        existingConsole.put(name, ecpsuID);
        System.debug('Existing '+name +' User Ids: ' + ecpsa);

    }
  }

  public String migratePermSet(String oldPS, String newPS) {
    List<PermissionSetAssignment> migratePS  = new List<PermissionSetAssignment>();
    List<PermissionSetAssignment> lpsuID = [
        SELECT AssigneeId
        FROM PermissionSetAssignment
        WHERE IsActive=true
          AND PermissionSetId = :psIDs.get(oldPS)
          AND AssigneeId NOT IN :existingConsole.get(newPS)
    ];

    for(PermissionSetAssignment a : lpsuID){
        System.debug('Migrate '+oldPS+' User: ' + a.AssigneeId + ' to '+newPS);

        migratePS.add( new PermissionSetAssignment (
            PermissionSetId = psIDs.get(newPS),
            AssigneeId =  a.AssigneeId
        ));

        if( migratePS.size() > 200) {
            upsert migratePS;
            migratePS.clear();
        }
    }
    if( migratePS.size() > 0) {
        try {
            insert migratePS;
        } catch(DmlException e) {
            System.debug('error: ' + e);
        }
      migratePS.clear();

    }
    return 'done';
  }
}


GRAXLegacyPerm glp = new GRAXLegacyPerm();

glp.migratePermSet('GRAX_Configuration_Admin', 'GRAX_Console_Admin_User');
glp.migratePermSet('GRAX_Advanced_User', 'GRAX_Console_Power_User');
glp.migratePermSet('GRAX_User', 'GRAX_Console_Standard_User');
```

Click "Execute."
{% endstep %}
{% endstepper %}


# Migrating from First Generation to Second Generation Managed Package

## Overview

This guide provides step-by-step instructions for migrating from the soon to be deprecated First [Generation Managed Package](https://documentation.grax.com/reuse-data/managed-package/first-generation) to the [Second Generation Managed Package](https://documentation.grax.com/reuse-data/managed-package/second-generation).

The Second Generation package offers:

* Reduced custom code in your org
* Elimination of secrets stored within Salesforce
* Faster implementation and easier maintenance
* New Lightning Web Components including Global Search
* Leverages modern Salesforce packaging tools

{% hint style="info" %}
**Important:** Both packages can coexist in your Salesforce org during the migration process, allowing you to minimize downtime for your users.
{% endhint %}

## Prerequisites

The following are required before beginning this migration:

* **GRAX Application:** Ensure you have a healthy GRAX application running with Backup enabled
* **Salesforce Permissions:** You need permissions to install/uninstall Managed Packages (System Admin profile is sufficient)
* **Testing Environment:** We strongly recommend testing this migration in a sandbox org before executing in production

### Migration Process Overview

* [Document current First Generation component usage](#document-current-first-generation-component-usage)
* [Install Second Generation Managed Package](#install-second-generation-managed-package)
* [Configure Second Generation settings](#configure-second-generation-settings)
* [Update page layouts with Second Generation components](#update-page-layouts-with-second-generation-components)
* [Verify Second Generation functionality](#verify-second-generation-functionality)
* [Uninstall First Generation Managed Package](#uninstall-first-generation-managed-package)

#### Document Current First Generation Component Usage

Before making any changes, document where First Generation components are currently deployed.

1. Open `Setup` in Salesforce
2. Use `Quick Find` to navigate to `Lightning App Builder`
3. For each page that contains GRAX components:
   * Note the object type (e.g., Case, Account, Contact)
   * Document which GRAX components are present
   * Record any custom configuration settings for each component
   * Take screenshots if helpful

{% hint style="info" %}
This documentation will be your reference when adding Second Generation components later.
{% endhint %}

### Install Second Generation Managed Package

The Second Generation package can be installed while First Generation is still running, preventing downtime for your users.

#### Choose the Correct Installation Link

**For Production Orgs** (including Developer Edition):

* Use: <https://getgrax.co/prod-gen2>

**For Sandbox Orgs:**

* Use: <https://getgrax.co/sandbox-gen2>

For detailed installation information, see the [Second Generation Installation Guide](https://documentation.grax.com/reuse-data/managed-package/second-generation/install).

#### Install the Package

1. Log in to your Salesforce org as a System Administrator
2. Open the appropriate installation link above
3. On the package installation screen, select `Install for All Users` (recommended) or `Install for Admins Only`
   * `Install for All Users`: Enables all internal users to access Second Generation components immediately
   * `Install for Admins Only`: Requires manual permission assignment later for non-admin users
4. Click `Install`
5. Wait for the installation to complete (typically less than one minute)
6. You will receive a confirmation email when installation succeeds

**If you installed for** `Admins Only` and later need to grant access to other profiles:

1. Go to `Setup` > Installed Packages
2. Locate `GRAX Lightning Web Components`
3. Click `View Components`
4. For each component (Versions Apex Class, CustomSettings Apex Class):
   * Click `Security`
   * Add the required user profiles
5. Assign the GRAX Search Tab to desired Salesforce user apps

### Configure Second Generation Settings

The Second Generation package requires configuration before components will function.

#### Configure Custom Settings

* In `Setup`, use `Quick Find` to search for `Custom Settings`
* Find `GRAX Settings` and click `Manage`
* Click `New` to create an organization-level default setting
* In the `GRAX URL` field, enter your GRAX application URL:
  * Format: `https://[your-grax-domain].com`
  * Click `Save`

{% hint style="danger" %}
Ensure that there is no trailing slash in the `GRAX URL` field
{% endhint %}

#### Configure Trusted URL for GRAX Application

* In `Setup`, use `Quick Find` to search for `Trusted URLs`
* Click `New Trusted URL`
* Configure the following:
  * **API Name:** `GRAX_Application` (or any name you prefer)
  * **URL:** Your GRAX application URL (same as Custom Settings, e.g., `https://mycompany.grax.io`)
  * **Check:** `frame-src`
  * **Leave checked:** `img-src`
* Click `Save`

#### Configure Trusted URL for GRAX HQ

* Still in `Trusted URLs,` click `New Trusted URL` again
* Configure the following:
  * **API Name:** `GRAX_HQ` (or any name you prefer)
  * **URL:** `https://hq.grax.com`
  * **Check:** `frame-src`
  * **Leave checked:** `img-src`
* Click `Save`

### Update Page Layouts with Second Generation Components

Now that Second Generation is installed and configured, update your page layouts to use the new components.

#### Understanding Component Differences

**Second Generation includes three components:**

* `Related Records`: View related records (live, deleted, or archived)
* `Record Versions`: Explore single-record history and restore data
* `Global Search`: Search for data within GRAX using filters and conditions

For detailed information about each component, see the [Second Generation Features Guide](https://documentation.grax.com/reuse-data/managed-package/second-generation/features).

#### Update Each Page Layout

For each page layout documented in [this step](#document-current-first-generation-component-usage):

* Navigate to the object record page in Salesforce
* Open the `Setup` sidebar (gear icon)
* Click `Edit [Object] Page` under Customization
* In the Lightning App Builder, find Second Generation components under `Custom - Managed`

{% hint style="danger" %}
Place GRAX components on a separate tab that is not loaded by default to improve page load times
{% endhint %}

* Drag the appropriate Second Generation component onto the page
* Configure the component settings

**Related Records Component Settings**

* `Related Object`: API name of the object type to display
* `Dataset Selection`: Choose All, Archived, Deleted, or Archived or Deleted
* `Child Level`: Hierarchy level (1 = immediate children, 2 = grandchildren, etc.)
* `Fields`: Comma-separated list of Field API names to display
* `Records Per Page`: Number of records per page
* `Override Title`: (Optional) Custom title
* `Height`: Component height
* `Additional Configuration`: (Optional) Advanced settings

**Record Versions Component Settings**

* `Records Per Page`: Number of versions per page
* `Override Title`: (Optional) Custom title
* `Height`: Component height
* Click `Save` to save the page layout
* Repeat for all page layouts that need GRAX components

#### Optional: Add Global Search Tab

The Global Search component can be added as a standalone Custom Tab:

* The GRAX Search Tab is automatically included with the Second Generation package
* Add it to relevant Salesforce apps via `App Manager`
* Configure search behavior via `Custom Settings` if needed:
  * `Search Tab: Template Search`: Enable for template-based search
  * `Search Tab: Show Template ID`: Specify a template ID to display

### Verify Second Generation Functionality

Before uninstalling First Generation, verify that Second Generation components work correctly.

#### Verification Checklist

* **Test Component Access:**
  * Log in as different user types (admin, standard user, etc.)
  * Navigate to pages with Second Generation components
  * Verify users can see the components based on their permissions
* **Test Component Functionality:**
  * Verify components load GRAX content correctly
  * Test Related Records component: confirm it displays related records
  * Test Record Versions component: confirm it shows record history
  * If applicable, test Global Search: run a search and verify results
* **Test Permissions:**
  * Confirm users with GRAX Console permissions can access components
  * Users should have one of these permission sets:
    * `GRAX Console Standard Permission`
    * `GRAX Console Seeding Permission`
    * `GRAX Console Purge Permission`
    * `GRAX Console Power Permission`
    * `GRAX Console Admin Permission`
* **First-Time User Authorization:**
  * Users must self-authorize the GRAX Connected App on first use
  * Have users open the GRAX application in a separate tab to complete authorization
  * Alternatively, admins can pre-authorize users via Connected App settings
* **Document Any Issues:**
  * Note any components that don't load correctly
  * Record any error messages
  * Contact support if you encounter unexpected behavior

{% hint style="danger" %}
Do not proceed to uninstall First Generation until Second Generation is fully verified.
{% endhint %}

### Uninstall First Generation Managed Package

Once Second Generation is verified and working, you can safely remove First Generation.

#### Prepare for Uninstallation

1. **Notify Users:** Inform users that First Generation components will be temporarily unavailable during uninstallation
2. **Remove First Generation Components from Page Layouts:**
   * Edit each page layout that has First Generation components
   * Remove the First Generation GRAX components
   * Save the page layouts
3. **Remove Permission Set Assignments:**
   * In `Setup`, navigate to `Permission Sets`
   * Find permission sets that start with `GRAX -`
   * Remove these permission sets from all users

#### Uninstall the Package

For detailed uninstallation information, see the [First Generation Uninstallation Guide](https://documentation.grax.com/reuse-data/managed-package/first-generation/uninstall).

1. In `Setup`, use `Quick Find` to search for `Installed Packages`
2. Find `GRAX` (First Generation) in the packages list
3. Click `Uninstall`
4. Check the confirmation checkbox
5. Click `Uninstall`

#### Handle Uninstall Errors

On the first attempt, you may receive errors about components still being used. Common issues include:

**Users still assigned permission sets:**

* Remove package permission sets (those starting with `GRAX -`) from all users

**Lightning Web Components still present in page layouts:**

* Remove First Generation components from all page layouts

**Apex classes still referenced in Scheduled Jobs:**

* Navigate to `Setup` > `Apex Jobs` > `Scheduled Jobs`
* Delete any jobs named `GRAXScheduledWorker`

#### Retry Uninstallation

* After resolving reported issues, repeat the uninstallation steps
* Continue resolving issues and retrying until uninstallation succeeds
* You will receive a confirmation email when uninstallation is complete

### Troubleshooting

#### Second Generation Components Not Loading

**Issue:** Components show blank or display errors

**Solutions:**

* Verify `Custom Settings` contain the correct GRAX application URL
* Verify both `Trusted URLs` are configured correctly
* Check that users have appropriate GRAX Console permission sets
* Confirm users have authorized the GRAX Connected App
* Verify the GRAX application is running and healthy

#### Users Cannot See Second Generation Components

**Issue:** Components are not visible to certain users

**Solutions:**

* If package was installed for `Admins Only`, manually assign component access to user profiles
* Verify users have GRAX Console permission sets assigned
* Check that the GRAX Search Tab is added to the user's Salesforce app

#### First Generation Uninstall Fails Repeatedly

**Issue:** Uninstallation continues to fail after resolving reported issues

**Solutions:**

* Check for custom code, workflows, or process builders that reference GRAX objects or classes
* Look for validation rules that reference GRAX fields
* Review all page layouts thoroughly for remaining First Generation components
* Contact GRAX Support for assistance

### Getting Help

If you encounter issues during migration or have questions not covered in this guide:

* **Review Documentation:**
  * [Second Generation Managed Package Overview](https://documentation.grax.com/reuse-data/managed-package/second-generation)
  * [Second Generation Features](https://documentation.grax.com/reuse-data/managed-package/second-generation/features)
  * [Second Generation Installation Guide](https://documentation.grax.com/reuse-data/managed-package/second-generation/install)
  * [First Generation Uninstallation Guide](https://documentation.grax.com/reuse-data/managed-package/first-generation/uninstall)
  * [Managed Package FAQ](https://documentation.grax.com/reuse-data/managed-package/frequently-asked-questions)
* **Contact GRAX Support:**
  * Visit: <https://documentation.grax.com/support/get-support>
  * Email: <help@grax.com>
  * Support is available to assist with migration issues


# Frequently Asked Questions

Second Generation Managed Package

<details>

<summary><strong>Don't I need the Managed Package to manage and utilize GRAX?</strong></summary>

No. The Managed Package is an optional add-on that provides unique ways to use GRAX data. All GRAX features besides the Lightning Web Components can be accessed via the GRAX Application's web interface.

</details>

<details>

<summary><strong>How do I know whether I have the First or Second Generation Managed Package installed?</strong></summary>

The First Generation Managed Package namespace is `grax`, while the Second Generation Managed Package namespace is `graxinc`.

</details>

<details>

<summary><strong>Can I have both the First Generation and Second Generation Managed Packages installed at the same time?</strong></summary>

Technically, yes you can. We do not recommend this as it may be difficult to decipher between the different components and permission sets.

</details>

<details>

<summary><strong>Are Files (ContentDocument/ContentDocumentLink/ContentDocumentVersion) compatible with the LWC?</strong></summary>

Yes. In order to see Files within the LWC, you'll need to install the LWC on the parent object of the File you'd like displayed in the LWC (For example, to see files linked to Case records, you'll need to install the LWC on the Case object page).

</details>

<details>

<summary><strong>Why don't I see the "GRAXLWCHelper" Apex Class in the "Enabled Apex Class Access" section?</strong></summary>

Whether you're able to see the `GRAXLWCHelper` Apex Class within the `Enabled Apex Class Access` of a profile is dependent on which [users were provided access to the managed package when it was installed](https://documentation.grax.com/reuse-data/managed-packages#installing-the-first-generation-managed-package).

If you're unable to see the `GRAXLWCHelper` Apex Class within the `Enabled Apex Class Access` of a profile, we recommend updating to the [latest version of GRAX](https://documentation.grax.com/reuse-data/managed-packages#installing-the-second-generation-managed-package) and selecting the `Install for Specific Profiles` option.

</details>


# Settings

The GRAX Application interface offers a new, streamlined method of managing the configuration and behavior of your GRAX Application. Access to the settings page is dependent on users possessing an administrator permission set via their Salesforce user. For more information about permissions management, see the [permissions documentation](/other/permissions-and-access/roles-for-end-users).

![GRAX Settings Page](/files/NaUncWMJWQAQ4NlGOSfC)

## Salesforce Panel

To manage the integration user, and thus the Salesforce org the GRAX Application is connected to, use the Salesforce panel in the GRAX settings tab. Here, you can view this information and click the `update` button to make any needed changes. You will also see your estimated storage usage within Salesforce and the number of total API requests made to Salesforce within the last 24 hours.

<figure><img src="/files/tlwE2A4dhOz2UlWQjzIl" alt=""><figcaption><p>Salesforce Connection Panel</p></figcaption></figure>

## Storage Panel

To manage the storage bucket connected to GRAX, use the "Object Storage" panel in the GRAX settings tab. Here, you can choose between AWS, Azure, or GCP storage buckets as well as enter supported credential sets.

![Storage Bucket Panel](/files/7DRRh3PnvrXnCwtXvveK)

## General Settings Panel

To manage the larger behavior of your GRAX Application, use the "General Settings" panel. Here, you can modify excluded objects, the schedules for auto updates, delete tracking, and metadata backups, as well as edit the behavior of restore. You can also set an "admin email address" which receives self-service emails when the app detects a supported failure.

![General Settings Panel](/files/dHAdWBJBywi5WOUpIbCL)

## Archive, Restore, and Seeding Panel

To manage how archives, restores, and seeds behave, use the "Archive, Restore, and Seeding" panel. Here, you can select objects to ignore from those processes, whether to allow them in production, setup behavior, how to handle `ContentDocumentLink` objects, record status check behavior, and sandbox seed targets.

![Archive, Restore, and Seeding Panel](/files/t2aCsKunzHIZYUk1cu2e)

## User Management

The `User Management` tab allows creation of local GRAX application users with independent credentials that do not require access to the connected Salesforce org. Local users should be created for team members who require access to the GRAX application but do not have Salesforce Org access, or to allow access to the GRAX application if the connected Salesforce Org is unavailable.

{% hint style="info" %}
GRAX recommends that each Production GRAX application have at least one local user to allow access if the Salesforce Org is unavailable and to enable Disaster Recovery.
{% endhint %}

To create a local user, take the following steps:

* Click on `New User`

![User Management](/files/zVRxs3W7yD0FgHHl1Ep2)

* Add the name and email address of the user
* Set the user's level of access

The user will receive an email prompting them to create a password, which, along with their email address, will be used to log into your GRAX Application via the `Sign in with Credentials` option. User details are accessible within the `User Management` section, and access can be revoked at any time. **Access will automatically be revoked after 30 days unless the user’s access has been set to never expire.**

{% hint style="warning" %}
The `User Management` functionality should not be used to grant GRAX Support access to your application. If you need to grant GRAX Support access to your application, please follow the steps detailed [here](doc:get-support#grant-grax-support-access-to-your-application).
{% endhint %}

## API Token Management

To access and manage API tokens, use the "API Token Management" panel. Here, you can create and destroy API tokens, and reveal legacy tokens if necessary.

![API Token Management Panel](/files/3ws3Wd8hsKZNWVfGTJJP)


# Connecting Salesforce

## Pre-Connection Considerations

Prior to connecting GRAX to Salesforce, let's review some important components of the connection process.

### GRAX Integration User

We require that you use dedicated Salesforce user and Permission Set for GRAX, rather than sharing a user and/or profile for GRAX and other integrations. This simplifies security, allows GRAX to automatically enforce and monitor permission problems, allows you to better audit issues, and maximizes concurrent API request limits that Salesforce imposes. GRAX uses this user for reading metadata and records for backup, deleting records for archives, and writing new records for restores. We refer to this user as the GRAX [Integration User](/other/permissions-and-access/integration-user).

### GRAX Auto Config

GRAX [Auto Config](/other/permissions-and-access/integration-user#auto-config) creates the `GRAX Integration user` permission set with the recommended configuration in Salesforce and assigns the permission set to the GRAX Integration User (the user you use to first connect the GRAX Application to your Salesforce org). This user is then used by GRAX to interact with Salesforce.

## Connecting a New GRAX Application to Salesforce

If you've just finished installing GRAX and it's reachable at `[your-grax-domain-and-port]/web`, you're all set to connect to Salesforce. You'll be greeted by this page:

<figure><img src="/files/TRcTr4Ou6fcKNrdpP7JP" alt="" width="563"><figcaption><p>Initial Auto Config Page</p></figcaption></figure>

* From the dropdown menu, select `Production` or `Sandbox` based on the type of org you are trying to connect.

{% hint style="warning" %}
Some Developer/Einstein orgs are considered production orgs by Salesforce.
{% endhint %}

* Click the `Connect with Auto Config` button
* You'll be directed to Salesforce and prompted to sign-in. **Be sure to sign-in as the `GRAX Integration User`**
* Follow the Salesforce OAuth login flow as normal, remembering to use your org's custom domain if applicable

{% hint style="info" %}
Once connected, the integration user may be reviewed or updated within the `Settings` tab of your GRAX Application.
{% endhint %}

A successful connection attempt lands you back on `[your-grax-domain-and-port]/login`, which looks slightly different now. Log in with your **individual Salesforce user** to enter the GRAX Application via SSO.

<figure><img src="/files/N49MsSQpaRQZvhVAgLyy" alt="" width="563"><figcaption><p>SSO Page for a Connected GRAX App</p></figcaption></figure>

## Changing or Moving Connections

If you've been using GRAX with a Salesforce org and would like to change the connected user or org, take the following steps:

* Click on the `Settings` tab
* Click on the `Salesforce` subtab
* Click `Update`

<figure><img src="/files/LiQXOGS6N0UZU5bZ2Tiq" alt="" width="454"><figcaption><p>Replace the Current Salesforce Connection</p></figcaption></figure>

* Click the `Connect with Auto Config` button
* You'll be directed to Salesforce and prompted to sign-in. **Be sure to sign-in as the `GRAX Integration User`**
* Follow the Salesforce OAuth login flow as normal, remembering to use your org's custom domain if applicable

#### Resetting GRAX

Resetting GRAX completely disconnects the GRAX App from Salesforce. In this state:

* Data backup and job history are not available
* Users will be unable to access GRAX with Salesforce credentials until a Salesforce connection is restablished
  * Set up [local users](/other/settings#user-management) before resetting GRAX if access is needed

Resetting GRAX is usually done as part of a [Sandbox Refresh](/other/settings/sandbox-refresh). To reset the GRAX App:

1. Navigate to `Settings`
2. Expand the `Salesforce` panel
3. Click `Reset GRAX`

<figure><img src="/files/3R2AkURQR4d68tvttSD0" alt="" width="454"><figcaption><p>Destroy the Current Salesforce Connection</p></figcaption></figure>

{% hint style="info" %}
Salesforce data backed up by GRAX is retained on the connected storage service after resetting GRAX. However, the data is not visible in GRAX without a connection to the source Salesforce org.
{% endhint %}

## What's Next?

If you're in the process of installing GRAX for the first time or need to otherwise (re)connect your longterm storage, see our [related documentation](/other/settings/connecting-storage).

## Frequently Asked Questions

#### Why is there an option to "Skip Auto Config"?

While GRAX Auto Config makes connecting to Salesforce more convenient by creating the `GRAX Integration user` permission set with the recommended configuration in Salesforce and assigning the permission set to the GRAX Integration User (the user you use to first connect the GRAX Application to your Salesforce org), some organizations may prefer to complete this setup manually. If your organization does not want to use the GRAX Auto Config functionality, choose `Skip Auto Config` when (re)connecting a new Salesforce org.


# Connecting Storage

There are a couple cases in which you need to connect GRAX to a longterm storage provider:

* New GRAX installations
* Changing storage credentials
* Moving to a different container/bucket/provider

Regardless of need, the storage configuration is always accessed the same way.

{% hint style="danger" %}
**Data Loss and Corruption Possible**

Never change your connected storage target in production without consulting with the [GRAX Support](/support/get-support) team. Changing the storage target after starting data backups risks corruption and/or loss of the entire dataset. For more information about how GRAX stores your data, see [here](/infrastructure/other/blob-storage).
{% endhint %}

## Supported Storage Platforms

The GRAX Application supports the following cloud storage platforms:

* Amazon Web Services (AWS) S3 and S3-compatible storage
* Microsoft Azure Blob Storage and Azure Data Lake Gen2
* Google Cloud Platform (GCP) Cloud Storage

The Storage Settings module allows you to choose the desired platform and adjusts the input form to match.

{% hint style="warning" %}
**Before you begin:** Ensure your cloud administrator has provisioned the storage bucket and credentials with the [appropriate permissions.](/infrastructure/other/blob-storage#required-permissions) See [Storage Requirements](/infrastructure/other/blob-storage) for details on what your cloud team needs to set up.
{% endhint %}

<figure><img src="/files/oHgeJkwJ8y1V61l6CkqY" alt=""><figcaption><p>Storage Settings Panel</p></figcaption></figure>

After saving changes, the app takes a minute or two to reboot and reconfigure. Once successfully connected, the module has a green "connected" indicator.

## Amazon Web Services (AWS) S3

### **Required Information**

* **Bucket Name** - The name of your S3 bucket
* **Bucket Region** - The AWS region where your bucket is located (e.g., `us-east-1`)
* **Access Key ID** - IAM user access key (not required if using Instance Role)
* **Secret Access Key** - IAM user secret key (not required if using Instance Role)

### **Connection Methods**

#### **Using EC2 Instance Role (Recommended)**

If your GRAX application and S3 bucket are in the same AWS account, you can use the EC2 Instance Role for authentication:

1. Fill in only the "Bucket Name" and "Bucket Region" fields
2. Leave "Access Key ID" and "Secret Access Key" empty
3. Click **Update Connection**

#### **Using IAM Access Keys**

If your cloud administrator provided IAM access keys:

1. Enter all four fields: Bucket Name, Bucket Region, Access Key ID, and Secret Access Key
2. Click **Update Connection**

#### **Using AWS Assume Role**

If your cloud administrator configured an Assume Role setup:

1. Enter the "Bucket Name" and "Bucket Region"
2. Enable "Use Assume Role"
3. Enter the "Assume Role ARN" provided by your cloud administrator
4. Enter the "External ID" if provided
5. Click **Update Connection**

{% hint style="info" %}
For details on configuring AWS Resources with Assume Role, contact your cloud administrator or review [Using AWS Assume Role](#using-aws-assume-role) below.
{% endhint %}

### Special Cases

#### Using EC2 Instance Role

EC2 instances are deployed with an assigned Instance Role. If your bucket and EC2 Instance/Role are located in the same AWS account, it's beneficial to use this Instance Role as the authentication method for S3 traffic. This allows you to authenticate GRAX with the bucket without a set of static IAM keys ever existing.

To connect to an S3 bucket via the Instance Role, fill in only the "Bucket Name" and "Bucket Region" fields of the storage configuration. The AWS SDK resolves the Instance Role credential provider and connects as long as the role has appropriate access.

#### Using AWS Assume Role

GRAX supports the use of AWS Assume Role for authentication into secondary accounts. This allows the S3 permissions to be managed in the account that owns the bucket and GRAX to be connected without static keys. The role or user that GRAX is authenticating with locally must be allowed to assume the remote role; this is managed in the account that owns the bucket and assumed role.

To configure the AWS resources for Assume Role **with a GRAX Cloud app**, follow the steps below. For self-managed deployments, the process is similar, but GRAX involvement isn't required.

1. Retrieve the AWS Account Number from GRAX.

   Open a GRAX Support ticket explaining the intention to use Assume Role for a GRAX Cloud app. GRAX provides the AWS account number for the account that must be allowed to assume the IAM role you'll create in the next step. If you'd like to require an External ID for the Assume Role, include that request in this ticket. GRAX provides the External ID value that can be required in the trust policy.
2. In your AWS account, create the S3 Policy with the template below, replacing `{BUCKET_ARN}` and `{KMS_ARN}` as needed. ([AWS Documentation](https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_create.html))

   **NOTE:** the KMS permissions and key mentioned in this template are only required if you plan to use KMS to encrypt S3 data differently than the default AES-256. ([AWS Documentation](https://docs.aws.amazon.com/AmazonS3/latest/userguide/UsingKMSEncryption.html))<br>

   ```json
   {
       "Version": "2012-10-17",
       "Statement": [
           {
               "Action": [
                   "kms:Decrypt",
                   "kms:DescribeKey",
                   "kms:Encrypt",
                   "kms:GenerateDataKey*",
                   "kms:ReEncrypt*"
               ],
               "Resource": "{KMS_ARN}",
               "Effect": "Allow"
           },
           {
               "Action": [
                   "s3:GetBucketVersioning",
                   "s3:ListBucket",
                   "s3:ListBucketMultipartUploads",
                   "s3:ListBucketVersions"
               ],
               "Resource": "{BUCKET_ARN}",
               "Effect": "Allow"
           },
           {
               "Action": [
                   "s3:AbortMultipartUpload",
                   "s3:DeleteObject",
                   "s3:GetObject",
                   "s3:ListMultipartUploadParts",
                   "s3:PutObject"
               ],
               "Resource": "{BUCKET_ARN}/*",
               "Effect": "Allow"
           }
       ]
   }
   ```
3. In your AWS account, create an IAM Role that trusts the provided AWS account number and attach the policy from the preceding step. ([AWS Documentation](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_create_for-user.html))
4. Provide the ARN of the role you created in the previous step to GRAX Support. GRAX Engineering creates the necessary IAM resources to allow the application to assume that role.
5. Enter the "Bucket Name" and "Bucket Region" fields and enable "Use Assume Role" on the storage settings panel. Enter the remote role's ARN into the "Assume Role ARN" field, as well as an external ID if enabled during role creation.

## **Microsoft Azure**

### **Required Information**

* **Storage Account Name** - The name of your Azure Storage Account
* **Storage Container Name** - The name of your container within the storage account
* **Access Key** - Storage Account access key

Your cloud administrator should provide these credentials after provisioning your Azure storage resources.

### **Connection Steps**

1. Select "Azure Blob" from the storage type dropdown
2. Enter the Storage Account Name, Storage Container Name, and Access Key
3. Click **Update Connection**

{% hint style="info" %}
For Private Endpoint setup details, see [Using Azure Private Endpoints](#using-azure-private-endpoints) below.
{% endhint %}

### **Special Cases**

#### Azure Data Lake Storage with Hierarchical Namespace

GRAX supports Azure Data Lake storage and its hierarchical namespace ([Azure reference doc](https://learn.microsoft.com/en-us/azure/storage/blobs/data-lake-storage-namespace#deciding-whether-to-enable-a-hierarchical-namespace)).

#### Using Azure Private Endpoints

GRAX supports the use of Azure Private Endpoints for connections to Azure Storage Accounts and the containers within them. Private Endpoints enable applications to interact with storage resources without those resources being publicly available and without relying on consistent source IP addresses. This aligns with Azure's documented "Best Practices." Private Endpoint connections to resources within your account need to be requested from the subscription running the application and approved in the subscription that owns the bucket.

When a Private Endpoint is used to connect to a Storage Account, that Storage Account can be set to allow no traffic from any Virtual Network nor Azure's Trusted Services list if you so choose. This prevents all access other than the Private Endpoint, including access via the Azure Portal, which may affect your end-users.

To configure the Azure resources for a Private Endpoint to a customer bucket **on any GRAX-managed deployment**, follow the steps below. For self-managed deployments, the process may involve the creation/configuration of additional network resources, such as a private DNS zone and supporting resource links.

1. Retrieve your target Storage Account ID from your Azure portal and send it to GRAX.

   Opening the JSON view on the Storage Account's "Overview" page makes this easiest. **Send this ID to** [**GRAX Support**](/support/get-support) along with identifying information for the environment you'd like to connect to that resource.
2. GRAX Engineering will modify the identified environment to include a Private Endpoint connection to the provided Storage Account ID.
3. Once the Private Endpoint is created, approve the connection in the subscription that owns the Storage Account. This is done by navigating to the "Private Endpoints" section of the Azure Portal and clicking "Approve" on the pending connection. The request message will identify GRAX-specific requests.
4. Once the Private Endpoint is approved, update your GRAX Application's storage connection to use the new Storage Account name, Storage Container name, and access key. It may take up to 15 minutes for an approved connection to reach a stable state, so try the connection a few times over a 15 minute period before contacting GRAX Support if issues occur.

## **Google Cloud Platform (GCP)**

### **Required Information**

* **Google Project ID** - Your GCP project identifier
* **Google Bucket Name** - The name of your storage bucket
* **Google Client Email** - The service account email address
* **Google Private Key** - The service account private key

Your cloud administrator should provide a Service Account JSON key file containing these credentials.

### **Extracting Credentials from the JSON Key File**

Your cloud administrator will provide a JSON file that looks like this:

```json
{
  "type": "service_account",
  "project_id": "my-grax-project",          ← Copy to Google Project ID
  "private_key": "-----BEGIN PRIVATE KEY-----\n...\n-----END PRIVATE KEY-----\n",  ← Copy to Google Private Key
  "client_email": "grax@my-project.iam.gserviceaccount.com",  ← Copy to Google Client Email
  ...
}
```

### **Connection Steps**

1. Select "GCP" from the storage type dropdown
2. **Google Project ID**: Copy the `project_id` value from the JSON file
3. **Google Bucket Name**: Enter the bucket name provided by your cloud administrator
4. **Google Client Email**: Copy the `client_email` value from the JSON file
5. **Google Private Key**: Copy the `private_key` value from the JSON file (see important note below)
6. Click **Update Connection**

{% hint style="warning" %}
The **Google Private Key** field requires only the `private_key` value from the JSON file. The private key should be a multi-line value (typically 25+ lines) that starts with `-----BEGIN PRIVATE KEY-----` and ends with `-----END PRIVATE KEY-----`. Paste the full key, including the BEGIN and END lines
{% endhint %}

## What's Next?

If you've made it here through installing GRAX and connecting to Salesforce, you're now all set to start backing up and harnessing your data. See [Backup documentation](/protect-data/backup) for more information on getting data backed up to GRAX.


# Sandbox Refresh

GRAX Application connections are impacted each time a Salesforce sandbox refresh takes place, however, getting GRAX up and running again in the new environment is a straightforward process.

## Why would a Sandbox get refreshed?

* To bring down a clean copy of the production environment to allow you to start the next project/test with a fresh and updated environment
* To start a new sandbox due to expiration of previous sandbox
* May be required as part of a software development cycle

{% hint style="info" %}
Please note that your sandbox will have a new org ID after the refresh.
{% endhint %}

## GRAX Sandbox Deployment Policy

Like Salesforce, GRAX monitors sandbox deployments for activity and automatically deletes deployments after a period of 180 days of inactivity. This improves security by cleaning up data, and cost by turning off unused servers. At any time you can deploy a new sandbox backend via [GRAX Platform](https://documentation.grax.com/platform/) or by [contacting GRAX Support](/support/get-support).

## Pre-Refresh Requirements

Before the refresh:

* Ensure that the `Admin Email Address` is set to one or more valid email addresses within the `Settings` section of the GRAX Application
* Disconnect Salesforce by [Resetting GRAX](/other/settings/connecting-salesforce#resetting-grax)
  * Navigate to `Settings`
  * Expand the `Salesforce` panel
  * Click `Reset GRAX`

<figure><img src="/files/3R2AkURQR4d68tvttSD0" alt=""><figcaption><p>Destroy the Current Salesforce Connection</p></figcaption></figure>

## Post-Refresh Reconfiguration

### GRAX Application Reconfiguration

* Login to your sandbox in SFDC as the GRAX Integration user
* Navigate to your GRAX App at `[your-grax-domain-and-port]/web` and follow the steps to [Connect Salesforce](/other/settings/connecting-salesforce#connecting-a-new-grax-application-to-salesforce)
  * Follow the prompts to Connect with Auto Config and restart Backup
* Navigate to `Settings` within the GRAX Application and expand the `Salesforce` section to confirm that the you are connected to the correct SFDC org with the correct Integration User. You will see a green dot followed by the word `Connected` if the connection is successful. If you need to modify the connection details, click `Update` to reset the connection

### GRAX Managed Package Reconfiguration

The GRAX Managed Package is optional and not all customers use it. If your organization uses the Managed Package, follow the steps below:

* Follow the [GRAX Application Reconfiguration](#grax-sandbox-deployment-policy) steps detailed above
* Navigate to the GRAX tab within SFDC
* [Configure GRAX in Salesforce](/reuse-data/managed-package)
* [Configure the Remote Site Setting](/reuse-data/managed-package)
* [Add your URL to the Trusted URLs list](/reuse-data/managed-package) if you see a banner at the top of the page prompting you to do so
* You can now navigate to the GRAX Application directly from SFDC via the `Schedule` and `Search` tabs


# Notifications

GRAX sends email notifications to keep you and your team aware of changes and insights about your data. These consist of:

* Data activities around search, archive, restore, and seeding
* User management around password changes
* Problems around Salesforce OAuth connection
* Periodic summaries around Backup, Archive and Data Lake usage

## App Notifications

GRAX sends real-time notifications for important events that happen in the app.

### App Admins

The app requires one or more valid admin emails to contact about critical problems like OAuth connection issues. To set these go to the [settings](/other/settings) and update "GRAX Admin Email Address" with a list of admins.

### Critical Notifications

| Type                      | Frequency | Description                                                                                                                               |
| ------------------------- | --------- | ----------------------------------------------------------------------------------------------------------------------------------------- |
| Salesforce Connection     | Daily     | [GRAX can't connect to Salesforce](#salesforce-connection-notifications)                                                                  |
| Storage Connection        | Daily     | [GRAX can't connect to bucket storage](#storage-connection-notifications)                                                                 |
| Missing Field Permissions | Weekly    | [GRAX is missing access to some previously synced object fields and can't back them up anymore](#missing-field-permissions-notifications) |

*Note that critical notifications don't send to sandboxes.*

### **Salesforce Connection Notifications**

Most lost connections to Salesforce are either a temporary timeout or a result of changes to your [GRAX Integration User](/other/permissions-and-access/integration-user).

* Connections issues are often temporary. As a first step, check if the connection is back up by clicking Settings in your left hand menu and check the status of the Salesforce connection.<br>

  <figure><img src="/files/YhlUCRQ098RB4ZQxLLtT" alt=""><figcaption><p>Salesforce Connection Panel</p></figcaption></figure>

  * If Salesforce is Green and "Connected," your Salesforce Connection is working.
  * If you receive multiple instances of this notification that self resolve, contact the [GRAX Support](/support/get-support) team to investigate the frequent disconnects.
* Reconnect your GRAX Integration user in the Salesforce Settings pictured above.
  * Take a screenshot of any errors you receive and provide them to your Salesforce Admin or GRAX Support if reconnecting does not work.
* Check with your Salesforce Admin team if there have been any recent changes that may have impacted the GRAX Integration user.
* Reference the documentation on [Connecting Salesforce](/other/settings/connecting-salesforce) for additional information.

### **Storage Connection Notifications**

Most lost storage connections are either a temporary timeout or a result of changes to your cloud infrastructure.

* Connections issues are often temporary. As a first step, confirm it is still down by checking Object Storage in your GRAX Application by clicking "Settings" in your left hand menu.<br>

  <figure><img src="/files/eg9VFmklMmvDjgRqYxYt" alt=""><figcaption><p>Storage Settings Panel</p></figcaption></figure>

  * If Object Storage is Green and "Connected," your Storage Connection is working
  * If you receive multiple instances of this notification that self resolve, contact the [GRAX Support](/support/get-support) team to investigate the frequent disconnects.
* Check with your Cloud Infrastructure team if there have been any recent changes that may have blocked GRAX access to the storage location.
* Verify the correct authentication settings for your Storage Connection in Settings.
* Reference the documentation on [Connecting Storage](/other/settings/connecting-storage),

{% hint style="danger" %}
**Data Loss and Corruption Possible**

Changing the storage target after starting Backup risks corruption and/or loss of the entire dataset. For more information about how GRAX stores your data, see technical documentation on [Longterm Storage](/infrastructure/other/blob-storage).
{% endhint %}

### **`Missing Field Permissions` Notifications**

You'll receive `Missing Field Permission` notifications when GRAX has identified at least one object that has missing field permissions.

See our [Missing Field Permissions doc](/protect-data/backup/missing-field-permissions) for additional details about the `Missing Field Permissions` tool and how to correct missing field permissions.

### Notification Feed

In the App, click the user icon in the upper right, then "Notifications" to see a feed of all your notifications.

## Periodic Notifications

GRAX also sends occasional updates like a monthly data summary, monthly newsletter, product announcements and usage surveys.

To unsubscribe from these notifications, use the unsubscribe link in the email footer.

## Additional Information

If you need additional assistance with Critical Notifications contact the [GRAX Support](/support/get-support) team.


# Insights

GRAX Insights provides real-time visibility into your data operations by displaying performance data for core GRAX Product features, Salesforce usage, and related metrics in a single location

{% hint style="info" %}
Insights charts automatically appear for features that are enabled and actively used by your account
{% endhint %}

#### Range

In the top left corner of the Insights page is the time range selector. Modifying the time rage will update the data shown for all charts on the Insights page.

<figure><img src="/files/xXuDEkADUH8ibnt6VSd2" alt="" width="282"><figcaption></figcaption></figure>

### Available Insight Charts

#### Data Backup Health

Displays the total of records created and updated by [GRAX Backup](/protect-data/backup) over time.

<figure><img src="/files/gZHforDhCoNxKpPOr3Uf" alt=""><figcaption><p>Data Backup Health Insights</p></figcaption></figure>

#### API Usage

Tracks your remaining Salesforce API calls over time, allowing you to monitor API consumption.

<figure><img src="/files/y3F4ZZyhiOzM1njAg8cU" alt=""><figcaption><p>API Usage Insights</p></figcaption></figure>

{% hint style="info" %}
API Usage displays all Salesforce API usage, not only API calls from GRAX.
{% endhint %}

#### Data Creation Rate

Provides an overall rollup with estimated record Salesforce storage metrics, showing records created, archived, deleted, and net total changes.

<figure><img src="/files/VX0aHXCC2H5ufnqqA2Zi" alt=""><figcaption><p>Data Creation Rate Insights</p></figcaption></figure>

{% hint style="info" %}
Record Storage in KiB shows estimated Salesforce storage usage and is calculated with [this method](https://help.salesforce.com/s/articleView?id=000383664\&type=1) from Salesforce.
{% endhint %}

#### Archive Performance

An overview of [archive](/protect-data/archive) performance and impact on Salesforce based on the top 5 archived objects, as well as a consolidated rollup of all other objects. The Salesforce Storage is shown as a trend line and read based on the left `Storage in MiB` scale. Records archived by object are shown as a stacked bar chart as read using the right `Records` scale. Rollups of Archive Metrics included the current vs previous range storage impact and error rates are shown at the bottom of the chart when tiled or on the left when expanded. The expanded view of the Archive Performance chart, with metrics on the left, is also displayed at the top of the Archive overview (main) page.

<figure><img src="/files/g3q1yt7DcgSRI92pUGcI" alt=""><figcaption><p>Archive Performance Insights</p></figcaption></figure>

#### Delete Protection

A summary of activity captured by the [Delete Tracking](/protect-data/backup/delete-tracking) feature, including total records deleted and deleted records per object. The Delete Protection chart is also displayed on the Delete Tracking overview (main) page

<figure><img src="/files/fD0tim5xy9Kni5WI6dha" alt=""><figcaption><p>Delete Protection Insights</p></figcaption></figure>

#### Archived Records By Object

A breakdown of the number of records [archived](/protect-data/archive) by Salesforce object.

<figure><img src="/files/Ryt54XRGSgWADWNjQISJ" alt=""><figcaption><p>Archived Records by Object Insights</p></figcaption></figure>

#### Replicate Health

Displays the total of records created and updated by [GRAX Data Replication](broken://pages/f4hPQSACFl4HDnitH1Ov) over time.

<figure><img src="/files/jY1uUTpRJiKBb33eDXbO" alt=""><figcaption><p>Replicate Health Insights</p></figcaption></figure>


# Permissions and Access

For information on common topics, expand the related section below.

<details>

<summary><strong>Integration User Permission Requirements</strong></summary>

The GRAX "Integration User" is the Salesforce User entity that GRAX performs all operations against your org as. This means that data is created, read, updated, and deleted in the context of this user's permissions. To best protect your org and its data, a high degree of access is required, often including permissions that are not commonly granted to Salesforce integrations that operate in a more focused capacity.

For more information on how to set up an Integration User or its profile/permission sets, as well as how to use the Missing Field Permissions and Auto Config tools, see the [Integration User](/other/permissions-and-access/integration-user) page.

Connecting a GRAX application to a Salesforce org with an Integration User also depends on the GRAX OAuth Connected app being properly configured, which is explained on the [Connected App](/other/permissions-and-access/connected-app) page.

</details>

<details>

<summary><strong>Role Based Access Control for End Users</strong></summary>

Whether monitoring Backup progress, managing Archive jobs, running Searches, viewing the Lightning Web Components, or otherwise using the application, every end-user will need to log in. For typical use, this is accomplished by Single Sign On via the Salesforce Org that is attached to the app. To control the features that each user can access, GRAX supports Role Based Access Control via assigning special Permission Sets to each Salesforce user.

For more information on the available roles, the features each role has access to, and how to manage the required Permission Sets with Auto Config, see the [Roles for End Users](/other/permissions-and-access/roles-for-end-users) page.

The ability for users to SSO within the GRAX application also depends on the GRAX OAuth Connected app being properly configured, which is explained on the [Connected App](/other/permissions-and-access/connected-app) page.

</details>

<details>

<summary><strong>Tokens for API Access</strong></summary>

For integration with third-party systems or the construction of customized user experiences that include GRAX data, developers can take advantage of the APIs served on every GRAX application server. These APIs are private per application. Administrators can:

* Create named tokens with different feature access levels
* Exclude a token from Field Level Security restrictions
* Review all existing tokens, who created them, and their permissions
* Disable an existing token immediately

For more information on API Tokens including how to create them and how to use them, see the [API Tokens](/other/permissions-and-access/api-tokens) page.

For more information on the GRAX API including an OpenAPI specification, see <https://api.grax.com>. For an interactive version of this documentation, add `/scalar` to your app's domain.

</details>

<details>

<summary><strong>Local Users</strong></summary>

Under normal conditions, the GRAX application depends on Salesforce to serve as an identity provider for the purposes of login and authentication. For the purposes of recovery when disconnected from Salesforce, access when running in "disconnected" mode, and access by teams that may not have Salesforce users, GRAX allows the creation of "Local" users.

For more information about local users including how to create them and delete them, see the [Local Users](/other/permissions-and-access/local-users) page.

</details>


# Oauth Overview

## OAuth Connection Overview

### What is OAuth?

OAuth (Open Authorization) is an industry-standard protocol that allows GRAX to securely access your Salesforce data without storing your credentials. When you connect GRAX to Salesforce, OAuth handles the authentication and authorization process.

### How GRAX Uses OAuth

GRAX uses OAuth for two purposes:

1. [**Integration User Connection**](#integration-user): A dedicated Salesforce user that performs backup, restore, and archive operations
2. [**End User Single Sign-On (SSO)**](/other/permissions-and-access/roles-for-end-users): Individual users log into the GRAX Application using their Salesforce credentials. Note: End-user access is validated by the Integration User's OAuth connection, so the Integration User must include the `id` scope (or `profile`, `email`) in its OAuth token.

### OAuth Connection Architecture

When GRAX connects to Salesforce, a secure multi-party flow occurs:

1. The GRAX backend initiates an OAuth request through `hq.grax.com`
2. This request is proxied to Salesforce using a unified GRAX Connected App
3. Access tokens are generated and passed back to the GRAX backend
4. No credentials or tokens are stored beyond the lifetime of specific authorization events

**Key Security Features:**

* All data stores are encrypted
* Login attempts originate from IP address `3.232.229.75`
* GRAX respects Salesforce field and record-level security

For complete technical details, see the [Authentication documentation](https://documentation.grax.com/security/authentication).

### Common OAuth Scenarios

#### Initial Connection

To connect GRAX to Salesforce using OAuth:

1. Navigate to your GRAX Application
2. Select Production or Sandbox based on your org type
3. Click "Establish OAuth Connection to Salesforce"
4. Complete the Salesforce login flow
5. Log in with your individual user via SSO

**Learn more:** [Connecting Salesforce](/other/settings/connecting-salesforce)

#### After Sandbox Refresh

If GRAX loses connection after a sandbox refresh, you'll receive reset emails with a link to reconnect.

**Learn more:** [Sandbox Refresh](/other/settings/sandbox-refresh) and [Handling Loss of Salesforce Connection](/other/settings/sandbox-refresh#post-refresh-reconfiguration)

#### After Enhanced Domain Changes

After Salesforce Enhanced Domain changes, navigate to your GRAX Application URL with `/web` appended and sign in with Salesforce to reestablish the connection.

**Learn more:** [Troubleshooting documentation](/other/troubleshooting#does-grax-support-enhanced-domains)

#### OAuth Errors During Connection

If you encounter OAuth errors:

1. Verify "Approve Uninstalled Connected Apps" permission on the connecting user
2. Check that the GRAX Connected App is installed
3. Verify network connectivity and IP whitelisting

**Learn more:** [Connected App troubleshooting](/other/permissions-and-access/connected-app#troubleshooting)

### Related Documentation

* [Authentication](https://documentation.grax.com/security/authentication#oauth-flow) - Complete OAuth flow and security details
* [Connected App](/other/permissions-and-access/connected-app) - Installation and configuration
* [Integration User](/other/permissions-and-access/integration-user) - User requirements and setup
* [Connecting Salesforce](/other/settings#salesforce-panel) - Step-by-step connection guide
* [Network Requirements](https://documentation.grax.com/infrastructure/requirements/network-requirements) - Required network access for GRAX Deployments
* [Troubleshooting](/other/troubleshooting) - Common issues and solutions


# Integration User

For optimal security and performance, we require the use of a dedicated Salesforce user and permission set for GRAX, rather than sharing a user and/or profile for GRAX and other integrations. This simplifies security, allows GRAX to automatically enforce and monitor permission problems, allows you to better audit issues, and maximizes concurrent API request limits that Salesforce imposes. GRAX uses this user for reading metadata and records for backup, deleting records for archives, and writing new records for restores. We refer to this user as the GRAX Integration User.

## Creating an Integration User

Within Salesforce, create a dedicated integration user for GRAX with access to all objects you wish to back up. We recommend using a clear and descriptive name, such as `GRAX Integration`. This user needs a User License of `Salesforce`. The `System Administrator` profile is the easiest to get started with.

{% hint style="info" %}
The SFDC Free Platform Integration User license (API-only users) cannot be used for the GRAX Integration user as this license type does not support several of the high level permissions required by GRAX.
{% endhint %}

## Integration User Permissions

### Auto Config

GRAX Auto Config automatically creates the `GRAX Integration user` permission set with the recommended configuration in Salesforce and assigns the permission set to the GRAX Integration User (the user you use to first connect the GRAX Application to your Salesforce org). This user is then used by GRAX to interact with Salesforce

### Overview

Required permissions are feature-specific where possible, allowing users to scope GRAX access as narrowly as possible for their use case while protecting against data loss where necessary. The table below illustrates the permissions required by each major feature. For rows marked "recommended," the GRAX product won't block usage of the feature without the related permission, but care should be taken to avoid data loss.

{% hint style="info" %}
For compatibility with GRAX-provided scripts, these permissions must be assigned via a Permission Set named `GRAX_Integration_User`. This Permission Set is created automatically by GRAX Auto Config; do not manually create a Permission Set with this name.
{% endhint %}

| Feature          | Permission          | Required/Recommended | Notes                                                                                                                                                                                                                           |
| ---------------- | ------------------- | -------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| All Features     | API Enabled         | Required             | Required for login and API access by the integration user.                                                                                                                                                                      |
| Backup (Records) | View All Data       | Recommended          | Ensures that records are included in Backup regardless of sharing rules.                                                                                                                                                        |
|                  | View Encrypted Data | Recommended          | Ensures that encrypted fields are included in the Backup. Omitting this causes encrypted fields to be absent from backup data.                                                                                                  |
| Backup (Files)   | Query All Files     | Required             | Ensures access to read all files for backup regardless of library and sharing rules. Omitting this may lead to a significant number of files being missed in Backup.                                                            |
| Archive          | View All Data       | Recommended          | Ensures Archive verification can find and match against necessary records. Omitting this may cause Archive verifications to fail.                                                                                               |
|                  | Modify All Data     | Recommended          | Ensures records contained within the Archive are able to be deleted. Omitting this may cause Archive executions to fail during the delete phase.                                                                                |
| Restore          | Modify All Data     | Recommended          | Ensures records can be updated and modified to match the record versions being restored. Omitting this may cause Restores to fail during record modification/creation.                                                          |
|                  | Create Audit Fields | Recommended          | Ensures original audit field values can be written for restore. Omitting this causes restored records to list the integration user as the source of creates or modifications to records instead of the original editor/creator. |
| Insights         | Manage Users        | Recommended          | Ensures that GRAX can monitor data and file storage details, enabling proactive management of your Salesforce storage quota and providing visibility into the impact of archiving.                                              |

{% hint style="info" %}
To grant the `Set Audit Fields upon Record Creation` permission, you must first enable it at the organization level under the `User Interface` menu within Setup. Look for the two-in-one option labeled "Enable 'Set Audit Fields upon Record Creation' and 'Update Records with Inactive Owners' User Permissions." See the [Enable the 'Create Audit Fields' permission guide](https://help.salesforce.com/s/articleView?id=000334139\&type=1).
{% endhint %}

### Field Level Security

Given how SFDC permission sets work, even when `View All Data` is given it's possible that GRAX is missing access to read fields on objects in a way that is transparent to the Integration User. This can lead to fields missing completely from your backups. GRAX addresses this limitation in several ways:

1. GRAX [Auto Config](#auto-config) will automatically set all known fields to be readable by the Integration User permission set during initial setup.
2. All users will be shown a warning banner explaining how many objects and fields are missing Field Level access when they log in to GRAX.
3. GRAX provides an in-app tool for resolving Field Level Security issues on demand without the need to manually update each object yourself.

### Recommended User Settings

These settings modify the Salesforce features that users are allowed to access. Without these, GRAX may not be able to read certain portions of Salesforce data. They can be assigned from the `User` page within Salesforce Setup.

| Permission                  | Comments                                                                        |
| --------------------------- | ------------------------------------------------------------------------------- |
| Salesforce CRM Content User | Ensures access to read and write all Content Documents and related binary data. |
| Marketing User              | Ensures access to read Campaign and related objects.                            |

## Mitigating Security Risks

Due to the nature of the GRAX Application, it is important to understand the security risks associated with the GRAX Integration User. The GRAX Integration User is a highly privileged user that has access to all data in your Salesforce org. This user is used to read, write, and delete data in your Salesforce org. If this user is compromised, it could lead to data loss or data corruption. To mitigate this risk, we recommend the following:

1. *Enable Multi-Factor Authentication (MFA) for the GRAX Integration User.*

   MFA is only required at time of login, after which GRAX will use a refresh and access token to interact with Salesforce. The Salesforce admin will need an MFA code at the time of setting up GRAX, but will not need to provide an MFA code again unless the refresh token is revoked or expires.
2. *Restrict login IP address ranges for the Integration User's profile.*

   Logins and requests will only come from GRAX's HQ server, the VM running your GRAX environment, and any admins who may need to set up GRAX initially. This means only 4 static IP addresses need to be allowed to log in as the GRAX Integration User in most cases.
3. *Enforce login IP ranges on every request.*

   This is a Salesforce setting that enforces the IP login ranges on every request instead of just at login. Documentation can be found [here](https://help.salesforce.com/s/articleView?id=000387787\&type=1). This can prevent hijacking of a session and reuse by malicious actors.
4. *Lock sessions to the IP address from which they originated.*

   This is another Salesforce setting that prevents sessions from changing IP after creation including switching between allowed IP ranges. Documentation can be found [here](https://help.salesforce.com/s/articleView?id=000380975\&type=1).
5. *Enable "API Only" restrictions on the Integration User's profile.*

   This prevents the user from having UI access to your Salesforce org. While this doesn't limit the user's data access, it limits the usability of the user if compromised. Documentation can be found [here](https://help.salesforce.com/s/articleView?id=sf.integration_user.htm\&type=5).

More information on secure best-practices for Integration Users can be found [here](https://admin.salesforce.com/blog/2023/best-practices-for-configuring-your-integration-user).

## Integration User Token Refresh

There may be the occasional need to refresh the tokens associated with the integration user due to a sandbox refresh, expired/revoked tokens, or server configuration changes. If this is the case, you will receive an email notification and you will also see a banner notification within the GRAX Application upon admin log-in. To reauthorize the Integration User, either click on the `GRAX Auto Config` button in the email and follow the prompts, or navigate to the `Settings` page in the application, expand the `Salesforce` section, click on `Update` in the blue box, and follow the prompts.

## Troubleshooting

GRAX Integration User needs a Salesforce License

When we create the `GRAX Integration User` PermissionSet so it can backup all data in your organization, this may include accessing managed packages that require a user license. If the required licenses are not granted to the GRAX Integration User, the Auto Config script will be blocked from adding the user to the `GRAX Integration User` PermissionSet. Unfortunately Salesforce doesn't provide any detail on what licenses are required through the APIs. To resolve:

1. Open the Settings page in Salesforce
2. Use the quick find to find the `Users` page
3. Open the GRAX Integration User
4. Click on `Permission Set Assignments` and choose `Edit Assignments`
5. Try to add `GRAX Integration User Permission` to the `Enabled Permission Sets` and click `Save`
   1. The error that pops up may have details of the License required.
6. Go back to the GRAX Integration User
7. Click on the `Permission Set License Assignments` and choose `Edit Assignments`
8. Add any licenses that are not included in the Standard User License
9. Repeat from Step 4 until the GRAX Integration User is successfully added to the `GRAX Integration User Permission` Permission Set

## Reference Docs

* [API Enabled Permission](https://help.salesforce.com/s/articleView?id=000331470\&type=1)
* [View All Data Permission](https://help.salesforce.com/s/articleView?id=sf.users_profiles_view_all_mod_all.htm\&type=5)
* [Modify All Data Permission](https://help.salesforce.com/s/articleView?id=sf.users_profiles_view_all_mod_all.htm\&type=5)
* [Query All Files Permission](https://help.salesforce.com/s/articleView?id=000353032\&type=1)
* [Set Audit Fields upon Record Creation Permission](https://help.salesforce.com/s/articleView?id=000334139\&type=1)
* [Salesforce CRM Content User](https://help.salesforce.com/s/articleView?id=sf.content_initialsetup.htm\&type=5)
* [Marketing User](https://help.salesforce.com/s/articleView?id=sf.faq_campaigns_who_has_access.htm\&type=5)
* [View Encrypted Data](https://help.salesforce.com/s/articleView?id=sf.fields_about_encrypted_fields.htm\&type=5)
* [Licensing for Managed Packages](https://help.salesforce.com/s/articleView?id=sf.distribution_managing_licenses.htm\&type=5)
* [Field Level Security](https://help.salesforce.com/s/articleView?id=sf.emergency_response_service_fls.htm\&type=5)


# Scripts

These scripts are intended for use only when `Auto Config` does not work in your Salesforce org. They are not required for most customers.

## Creating the GRAX\_Integration\_User Permission Set manually

1. Open the [Salesforce Developer Console](https://help.salesforce.com/s/articleView?id=sf.code_dev_console_opening.htm\&type=5)
2. Open the `Debug` menu
3. Select `Open Execute Anonymous Window` (or press `CTRL + E`)
4. Copy the script below into the `Enter Apex Code` dialog
5. Select the `Open Log` checkbox
6. Click `Execute`
7. Assign the new '*GRAX\_Integration\_User*' permission set to the GRAX Integration User.

```apex
PermissionSet piu = new PermissionSet(
    Name = 'GRAX_Integration_User',
    Label = 'GRAX Integration User Permission',
    Description='Grants users permission to read and update records, fields and files for GRAX backup, archive and restore',
    PermissionsApiEnabled=true,
    PermissionsViewAllData=true,
    PermissionsModifyAllData=true,
    PermissionsQueryAllFiles=true
);

DescribeSobjectResult permissionSetDescribe = Schema.PermissionSet.SObjectType.getDescribe();
Map<String, SObjectField> fieldMap = permissionSetDescribe.fields.getMap();
List<String> availablePermissions = new List<String>();

for (String fieldName : fieldMap.keySet()) {
    if (!fieldName.startsWithIgnoreCase('Permissions')) {
        continue;
    }
    if (fieldName == 'PermissionsCreateAuditFields') {
        System.debug('Setting PermissionsCreateAuditFields=true');
        piu.put(fieldName, true);
    }
    if (fieldName == 'PermissionsViewAllData' ||
            fieldName == 'PermissionsModifyAllData' ||
            fieldName == 'PermissionsQueryAllFiles') {
                continue;
    }
    DescribeFieldResult fd = fieldMap.get(fieldName).getDescribe();
    if (fd.isCreateable() && fd.isUpdateable()) {
        availablePermissions.add(fieldName);
    }
}
Integer count = 1;

while (count < 11) {
    try {
        insert piu;
        count = 100;
    } catch(DmlException e) {
        count++;
        List<String> splitError = e.getMessage().split(' ');

        for (String str : splitError){
            string check = str.removeEnd(',');
            check = check.removeEnd(':');
            for (String fieldName : availablePermissions){
                if (fieldName == 'Permissions' + check){
                    piu.put(fieldName, true);
                }
            }
        }
    }
}
```

## Fixing Field Level Security manually

### Option 1: Apex FLS Script

The GRAX-provided Apex script below is an effective solution for updating field-level permissions on a large number of objects. However, there are a few cases in which the script may not be ideal:

1. Very large number of objects
2. Very large number of fields

The script makes a best effort to handle Apex row/batch limits. This means that you need to run the script multiple times if a large number of objects are processed. The script outputs `Apex batch limits reached. Please run again for next batch.` if another run is required.

If you encounter Apex limit errors, errors related to specific objects, or validation errors while running this script, fallback to the web-tools option below for updating the objects that remain.

**NOTE:** this section assumes you've used the script above to provision a `GRAX_Integration_User` Permission Set. If you don't have a permission set with this name in your org, the script fails.

**ALSO NOTE:** this script grants access to fields we're able to find in the Salesforce metadata. *This may not be a comprehensive list*. GRAX Admins should review the `GRAX_Integration_User` Permission Set's Field Permissions for each object to ensure access is granted to all fields.

#### **Running the FLS Script**

1. Open the [Salesforce Developer Console](https://help.salesforce.com/s/articleView?id=sf.code_dev_console_opening.htm\&type=5)
2. Open the `Debug` menu
3. Select `Open Execute Anonymous Window` (or press `CTRL + E`)
4. Copy the script below into the `Enter Apex Code` dialog
5. Select the `Open Log` checkbox
6. Click `Execute`
7. In the `Execution Log` window, select the `Debug Only` checkbox
8. If the last log entry prompts a re-run, return to the `Execute Anonymous Window` and repeat the subsequent steps until the last entry no longer prompts a re-run.

```apex
// decrease the maxBatchSize if a `System.LimitException: Too many query rows: 50001` error is returned
Integer maxBatchSize = 1000;

PermissionSet[] lpsGIU = [SELECT Id FROM PermissionSet WHERE name = 'GRAX_Integration_User'];
if (lpsGIU.isempty()) {
    System.debug('GRAX_Integration_User PermissionSet not found');
    return;
}

// Use the 25 oldest permissionSets with ViewAllData Permissions to model the fields to grant access to
PermissionSet[] lpsModel = [
    SELECT Id
    FROM PermissionSet
    WHERE PermissionsViewAllData = true
    AND id != :lpsGIU[0].Id
    ORDER BY CreatedDate
    LIMIT 25];

List<Id> modelPSIds = new List<Id>();
for (PermissionSet psID : lpsModel) {
    Id tmpID = (Id) psID.get('Id');
    modelPSIds.add(tmpID);
}

if (modelPSIds.isempty()) {
    // No viewAllData PermissionSet were found, use the 25 oldest permissionSets
    PermissionSet[] lpsProfile = [
        SELECT Id
        FROM PermissionSet
        WHERE ProfileId != ''
        AND id != :lpsGIU[0].Id
        ORDER BY CreatedDate
        LIMIT 25];
    for (PermissionSet psID : lpsProfile) {
        Id tmpID = (Id) psID.get('Id');
        modelPSIds.add(tmpID);
    }
}

if (modelPSIds.isempty()) {
    System.debug('no PermissionSets to model');
    return;
}

system.debug(modelPSIds);

List<AggregateResult> aggHas = new List<AggregateResult>([
    SELECT SObjectType
    FROM FieldPermissions
    WHERE ParentID = :lpsGIU[0].Id
    GROUP BY SObjectType]);

Set<String> hasObj = new Set<String>();
for (AggregateResult obj : aggHas) {
    String tmpObj = (String) obj.get('SobjectType');
    hasObj.add(tmpObj);
}

List<AggregateResult> aggAll = new List<AggregateResult>([
    SELECT SObjectType
    FROM ObjectPermissions
    GROUP BY SObjectType
    ORDER BY SObjectType
]);

String [] objectsToFix = new List<String>();

for (AggregateResult obj : aggAll) {
    String tmpObj = (String) obj.get('SobjectType');
    if (!hasObj.contains(tmpObj)){
        objectsToFix.add(tmpObj);
    }
    if (objectsToFix.size() >= maxBatchSize) {
        System.debug('Max batch size reached. Please run again for next batch.');
        break;
    }
}

List<AggregateResult> aggFP = new List<AggregateResult>([
        SELECT SObjectType, min(Id) Id
        FROM FieldPermissions
        WHERE SObjectType IN :objectsToFix
            AND ParentId IN :modelPSIds
        GROUP BY SObjectType, Field
    ]);

Map<String, List<Id>> fieldsToFix = new Map<String, List<Id>>();

for (AggregateResult fpID : aggFP) {
    String tmpObj = (String) fpID.get('SObjectType');
    Id tmpID = (Id) fpID.get('Id');
    if (fieldsToFix.containsKey(tmpObj)) {
        fieldsToFix.get(tmpObj).add(tmpID);
    } else {
        fieldsToFix.put(tmpObj, new List <Id> { tmpID });
    }

}

for(String obj : objectsToFix){
    if (Limits.getQueries() > 90 || Limits.getQueryRows() > 40000) {
        System.debug('Apex batch limits reached. Please run again for next batch. exiting');
        break;
    }
    if (!fieldsToFix.containsKey(obj)) {
        System.debug('No permissionable field found in object ' + obj + ' - skipping');
        continue;
    }
    list<FieldPermissions>dup=[
        SELECT Id, SobjectType, Field
        FROM FieldPermissions
        WHERE SObjectType = :obj
            AND ParentId = :lpsGIU[0].Id
    ];

    list<FieldPermissions>fields=[SELECT SobjectType, Field FROM FieldPermissions WHERE Id IN :fieldsToFix.get(obj)];

    Integer count = 0;
    List<FieldPermissions> listOfFieldPermissions = new List<FieldPermissions>();
    for(FieldPermissions fp : fields){
        count++;
        FieldPermissions newFP = new FieldPermissions(
            Field = fp.Field,
            SobjectType = fp.SobjectType,
            ParentId = lpsGIU[0].Id,
            PermissionsRead = true
        );
        for(FieldPermissions d : dup){
            if (fp.Field == d.Field) {
                newFP.id=d.id ;
            }
        }
        listOfFieldPermissions.add(newFP);
    }
    try {
        upsert listOfFieldPermissions;
        System.debug('Completed successfully for object ' + obj + ' - granted access to ' + String.valueOf(count) + ' fields ');
    } catch(DmlException e) {
        System.debug('Error updating [' + obj + ']: ' + e.getMessage());
    }
}
```

### Option 2: Web-tools Script Builder

GRAX Web-tools can generate an FLS script that is scoped to a single-object at a time. This prevents many issues with Apex limits that may result from the larger script above while still making life easy for SFDC admins.

#### **Generating and Running a Script**

1. Navigate to `/web/tools` on your GRAX Application, or use the link at the top right of the `Settings` page
2. Select the `Missing Field Permissions` option
3. Select the `Show Apex Script` option for the intended object
4. Copy the generated script to your clipboard
5. Open the [Salesforce Developer Console](https://help.salesforce.com/s/articleView?id=sf.code_dev_console_opening.htm\&type=5)
6. Open the `Debug` menu
7. Select `Open Execute Anonymous Window` (or press `CTRL + E`)
8. Copy the script below into the `Enter Apex Code` dialog
9. Select the `Open Log` checkbox
10. Click `Execute`
11. In the `Execution Log` window, select the `Debug Only` checkbox
12. The script outputs the number of corrected fields in the last log line.

Repeat the steps above for each necessary object.


# Roles for End Users

GRAX controls access levels via permission set assignments. Any user that wants to access GRAX must first have the proper Salesforce permission set assignments.

## What are the GRAX permission sets and what do they do?

The following permission sets grant the access detailed in the table below:

* `GRAX Console Standard Permission`: Standard User access per the table below
* `GRAX Console Seeding Permission`: Seeding User access per the table below
* `GRAX Console Purge Permission`: Purge User access per the table below
* `GRAX Console Power Permission`: Power User access per the table below
* `GRAX Console Admin Permission`: Admin User access per the table below
* `GRAX Console View All Fields`: Do not apply Field Level Security checks to this user in the GRAX Application (see below for more details)

The `GRAX Console Admin Permission` permission set is assigned to the GRAX Integration user account automatically otherwise these are created but not assigned. Please be sure to assign the proper level of access to all users that you want to access the GRAX Application.

| Feature          | Standard User    | Seeding User     | Power User       | Purge User       | Admin User             |
| ---------------- | ---------------- | ---------------- | ---------------- | ---------------- | ---------------------- |
| Backup Dashboard | `None`           | `None`           | `View`           | `None`           | `View` and `Configure` |
| Archive          | `None`           | `None`           | `View` and `Run` | `None`           | `View` and `Run`       |
| Restore          | `None`           | `None`           | `View` and `Run` | `None`           | `View` and `Run`       |
| Delete Tracking  | `None`           | `None`           | `View`           | `None`           | `View`                 |
| Sandbox Seeding  | `None`           | `View` and `Run` | `View` and `Run` | `None`           | `View` and `Run`       |
| Search           | `View` and `Run` | `View` and `Run` | `View` and `Run` | `None`           | `View` and `Run`       |
| Purge            | `None`           | `None`           | `None`           | `View` and `Run` | `View` and `Run`       |
| Data Lake        | `None`           | `None`           | `View`           | `None`           | `View` and `Configure` |
| Settings         | `None`           | `None`           | `None`           | `None`           | `View` and `Configure` |

To summarize the main differences between these 4 access levels:

* Standard User can lookup records by the ID and see record details, but cannot see any other features
* Purge User can purge records from the GRAX Data Vault
* Seeding User can run Global Search and Seed records into a sandbox
* Power User has nearly the same access as Admin User, but cannot see `Settings` and cannot configure objects for Search or Data Lake
* Admin User can see and do everything

You can find a call-out in the GRAX navigation menu stating the current logged in user's access level. Note that the permission sets are cumulative, such that the user has the highest level of access granted.

## How do I create the GRAX permission sets?

There are 2 supported ways to assign Salesforce permission sets.

#### Creating the GRAX Permission Sets via Auto Config

GRAX [Auto Config](/other/settings/connecting-salesforce#grax-auto-config) creates the following user access permission sets in Salesforce when you connect the GRAX Application to your Salesforce org the first time.

* `GRAX Console Standard Permission`
* `GRAX Console Seeding Permission`
* `GRAX Console Purge Permission`
* `GRAX Console Power Permission`
* `GRAX Console Admin Permission`
* `GRAX Console View All Fields`

#### Creating the GRAX Permission Sets Manually

The following script can be used to create GRAX permission sets using the Salesforce Developer Console:

1. Open the [Salesforce Developer Console](https://help.salesforce.com/s/articleView?id=sf.code_dev_console_opening.htm\&type=5)
2. Open the `Debug` menu
3. Select `Open Execute Anonymous Window` (or press `CTRL + E`)
4. Copy the script below into the `Enter Apex Code` dialog
5. Select the `Open Log` checkbox
6. Click `Execute`

```apex
PermissionSet pa = new PermissionSet(Name = 'GRAX_Console_Admin_User', Label = 'GRAX Console Admin Permission', Description='Grants users Admin User permissions to the GRAX console');
insert pa;

PermissionSet pf = new PermissionSet(Name = 'GRAX_View_All_Fields', Label = 'GRAX Console View All Fields', Description='Grants users access to view all fields in GRAX regardless of their Field Level Security permissions');
insert pf;

PermissionSet pp = new PermissionSet(Name = 'GRAX_Console_Power_User', Label = 'GRAX Console Power Permission', Description='Grants users Power User permissions to the GRAX console');
insert pp;

PermissionSet pr = new PermissionSet(Name = 'GRAX_Console_Purge_User', Label = 'GRAX Console Purge Permission', Description='Grants users Purge permissions to the GRAX console');
insert pr;

PermissionSet ps = new PermissionSet(Name = 'GRAX_Console_Seeding_User', Label = 'GRAX Console Seeding Permission', Description='Grants users Sandbox Seeding permissions to the GRAX console');
insert ps;

PermissionSet pu = new PermissionSet(Name = 'GRAX_Console_Standard_User', Label = 'GRAX Console Standard Permission', Description='Grants users Standard User permissions to the GRAX console');
insert pu;
```

## Why are there additional GRAX permission sets beyond those listed above?

Permission sets that do not begin with `GRAX Console` are legacy permission sets that have been replaced with the `GRAX Console` permissions detailed above.

Some of the legacy GRAX permission sets you may see are:

* `GRAX - Admin`
* `GRAX - Archive Master`
* `GRAX - Community User`
* `GRAX - Data Admin`
* `GRAX - Datahub Search Permission`
* `GRAX - Limited Admin`

These legacy permission sets are installed when you install the GRAX Managed Package for Salesforce. They control user access within the managed package, as well as within the GRAX Application and embedded experiences. **The following 3 legacy permission sets can still control user access.** Please see the equivalency table below for more details:

| Managed Package Salesforce Permission Set | Standard User Access | Power User Access    | Admin Access         |
| ----------------------------------------- | -------------------- | -------------------- | -------------------- |
| GRAX\_Configuration\_Admin                | :white\_check\_mark: | :white\_check\_mark: | :white\_check\_mark: |
| GRAX\_Advanced\_User                      | :white\_check\_mark: | :white\_check\_mark: |                      |
| GRAX\_User                                | :white\_check\_mark: |                      |                      |

## Field Level Permissions

In addition to the Access Levels above, GRAX applies field level permissions to all users logged in via SSO. This means you can restrict what fields they see in the GRAX Application the same way you'd do for any Salesforce user. The "View All Fields" modifier allows a user to see add fields on an object in GRAX, regardless of their Salesforce Field Level Security or the current object schema.

The following script can be used to create this GRAX permission set using the Salesforce Developer Console:

1. Open the [Salesforce Developer Console](https://help.salesforce.com/s/articleView?id=sf.code_dev_console_opening.htm\&type=5)
2. Open the `Debug` menu
3. Select `Open Execute Anonymous Window` (or press `CTRL + E`)
4. Copy the script below into the `Enter Apex Code` dialog

```apex
PermissionSet pv = new PermissionSet(Name = 'GRAX_View_All_Fields', Label = 'GRAX Console View All Fields', Description='Grants users access to view all fields in GRAX regardless of their Field Level Security permissions');
insert pv;
```

## Next Steps

To proceed with connecting GRAX to Salesforce and your storage platform of choice, start with our [connection documentation](/other/settings/connecting-salesforce).


# Connected App

Salesforce Connected Apps are a framework by which third party applications can integrate with Salesforce in a trusted fashion. A properly installed Connected App is necessary for GRAX to utilize your Integration User and for end-users to use Single Sign On to access GRAX. Additionally, Connected App settings can be customized to restrict access to GRAX or make it more seamless.

{% hint style="warning" %}

## **Recent Changes to Connected Apps**

As a result of recent Salesforce data breaches, changes have been made by Salesforce to limit access to Connected Apps and the ability to install/approve them. For more information on this change, see the [related Salesforce Knowledge Article](https://help.salesforce.com/s/articleView?id=005132365\&type=1).

**When a GRAX service connects to your Salesforce org for the first time, the "Approve Uninstalled Connected Apps" permission must\* be assigned to the authenticating user.** This permission does not need to be assigned to every user, and can be removed after initial installation of the Connected App.

\*exact restrictions are dependent on security restrictions in the org, including [API Access Control](https://help.salesforce.com/s/articleView?id=xcloud.security_api_access_control_about.htm\&type=5) settings.
{% endhint %}

## Installing the Connected App

The first time a GRAX service connects to your org, Salesforce will automatically try installing the related Connected App. Successful installation is necessary for any GRAX service to operate as designed. Whatever user is used to connect for the first time must have the following permissions:

* Customize Application
* Modify All Data OR Manage Connected Apps
* Approve Uninstalled Connected Apps

Most of these permissions are automatically assigned to the default System Administrator profile. Cloned and custom admin profiles will vary.

To view the connected apps that exist in your org as well as if they're installed, open the "Connected Apps OAuth Usage" page in setup.

<figure><img src="/files/VR8pdAhyxBvXLI4XIs0P" alt=""><figcaption></figcaption></figure>

When you first use a Connected App, you will be asked to confirm the installation:

<figure><img src="/files/gGwVbLJ6RfFNd2GX1dtP" alt=""><figcaption></figcaption></figure>

Once the app is installed, you will see "Uninstall" as an available action, as shown below:

<figure><img src="/files/iWlyE3ndYiAzMWW2vkfD" alt=""><figcaption></figcaption></figure>

If you encounter errors while connecting a GRAX service or installing the Connected App, double check the expected permissions listed above and the API Access Control settings within your organization.

## Customizing the Connected App

By clicking the "Managed App Policies" option in the "Connected Apps OAuth Usage" menu, administrators can modify the behavior of the connected app, the sessions associated with it, and the ability of users in the org to utilize the app. The option will not appear if the app is not installed.

<figure><img src="/files/eNVsptbzV6ki3mWKpzp5" alt=""><figcaption></figcaption></figure>

GRAX is not compatible with all possible options, and not all possible options have an effect on GRAX. Meaningful settings and their impact are broken out below.

| Setting              | Value                                   | Impact                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  |
| -------------------- | --------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Permitted Users      | All users may self-authorize            | All users in the org may SSO via the connected app, but will be individually asked for their consent and authorization of the app and associated scopes. This can interfere with use of the LWCs if users have never logged into GRAX before.                                                                                                                                                                                                                                                           |
|                      | Admin approved users are pre-authorized | <p>Users must be pre-approved based on assigned profile by an administrator, but will not need to individually consent to and authorize the app and associated scopes. This can make the LWC and SSO experience more seamless, but may be more of a burden to manage.<br><br>Enabling this option will immediately prevent all users in the org from using the app, regardless of whether they have authorized it previously. They must be authorized by profile before they can use the app again.</p> |
| IP Relaxation        | Enforce IP restrictions                 | Login requests using this connected app must come from one of the IPs configured within the user's "Login IP Ranges". If no ranges are configured for the user, this has no effect.                                                                                                                                                                                                                                                                                                                     |
|                      | Relax IP Restrictions                   | Login requests using this connected app are allowed regardless of the configured "Login IP Ranges" for a user.                                                                                                                                                                                                                                                                                                                                                                                          |
| Refresh Token Policy | Refresh token is valid until revoked    | This is the only supported value. GRAX will perpetually refresh the integration user connection until the refresh token is revoked by any means.                                                                                                                                                                                                                                                                                                                                                        |

## Troubleshooting

### OAuth Errors During Connection

If you encounter an OAuth error when attempting to connect to GRAX using Auto Config, Platform, or Quick Start, visit our [Connected App troubleshooting tool](https://start.grax.com/connected-app) for step-by-step guidance on resolving the issue and establishing your connection.


# API Tokens

Access to the endpoints documented at api.grax.com and served on every GRAX application is controlled via API tokens, which can be managed from within the related GRAX application. Tokens can be assigned limited feature access, named, and disabled.

## Creating an API Token

Tokens can be managed via the "API Tokens" section on the "Settings" page. Click "New Token" to configure your token permissions and name.

<figure><img src="/files/Hf2cG7R3nWyDBF9Gn7EH" alt="" width="524"><figcaption></figcaption></figure>

<figure><img src="/files/6T8lXw8OtSSrTcK7IrFA" alt="" width="451"><figcaption></figcaption></figure>

Once you've selected the permissions you want the token to have, click "Save" to create it. **The token value will only be shown once after creation.** You must store it in a safe location before leaving the page. If you lose it, you will need to create a new token.

<figure><img src="/files/oRdjCv53KcYv2fCC36pl" alt=""><figcaption></figcaption></figure>

## Deleting an API Token

Tokens can be deleted by clicking the trash can icon in the API Tokens list, shown above. A confirmation window ensures that tokens are not accidentally deleted.

<figure><img src="/files/w9LEigsffqv2uAMs5TcT" alt=""><figcaption></figcaption></figure>

## Using an API Token

Tokens are used for authenticating and authorizing requests to the GRAX application API. The tokens must be passed to the API as part of the Authorization header in every request.

For more information and examples, see the static API documentation at <https://api.grax.com> or the interactive API documentation at `/scalar` on your own GRAX application.


# Local Users

Local users can be used to access GRAX when:

* the connection to Salesforce becomes broken
* Salesforce is not available
* GRAX is running in "disconnected" mode
* users need access to GRAX data, but do not have Salesforce users

## Creating a Local User

Local users can be managed via the "User Management" panel on the application's "Settings" page. The list can be filtered to exclude users that are disabled for readability. The "New User" button shows the form for creating a new user.

<figure><img src="/files/w1DMZCGA00UkMLhGGvn2" alt=""><figcaption></figcaption></figure>

<figure><img src="/files/b2nXDDTczlMsJcFEv3P3" alt=""><figcaption></figcaption></figure>

Each user can be granted the [same roles](/other/permissions-and-access/roles-for-end-users) that Salesforce-based users and API tokens use. Each user can also be configured to automatically expire on a specific date, after which time they will no longer be allowed to log in to the application.

Once a user is created, click "Reset Password" on their edit form. They will receive an email allowing them to generate credentials for their new user.

## Disabling a Local User

Local users can be disabled to prevent further logins from that user. To deactivate the user, uncheck the "Is Active" checkbox in the user's edit form.

<figure><img src="/files/TZlQEFTgBK2SuTj9thFi" alt=""><figcaption></figcaption></figure>

## Logging in as a Local User

To use a local user's credentials to access a GRAX application, choose "Log in with Credentials" on the login page and enter your credentials. For local users, the username is the related email address.

<div data-full-width="false"><figure><img src="/files/PwF6U2cFZdUB39CWAFsO" alt="" width="375"><figcaption></figcaption></figure></div>

<figure><img src="/files/zq30BA3R5HG3MWj7lpuo" alt="" width="375"><figcaption></figcaption></figure>

## Limitations

Because local users are not backed by a related Salesforce user, some features may be unavailable or behave differently for them. This includes, in part, Field Level Security checks and dynamic record page layouts.

There are currently no limits on the number of local users that can be created. This is subject to change without notice.


# Frequently Asked Questions

<details>

<summary><strong>Why do users need to consent to and authorize "GRAX OAuth" the first time they log in?</strong></summary>

By default, connected apps are configured to allow all users to self-authorize that connected app when they start the OAuth process. When a user logs in to GRAX for the first time, they must tell Salesforce that they approve of the connected app and the access it is asking for to their user.

If you would like to avoid this prompt, use the "Permitted Users" setting within the connected app policies. Administrators can pre-authorize users based on assigned profile, which skips this per-user popup.

For more information, see the [Connected App](/other/permissions-and-access/connected-app) page.

</details>

<details>

<summary><strong>Why does GRAX need Manage User Permissions for "Intelligent archive recommendations"?</strong></summary>

Salesforce [requires the "Manage Users" Permissions](https://developer.salesforce.com/docs/atlas.en-us.api_rest.meta/api_rest/resources_limits.htm) to track Object Data and File Storage Usage. GRAX uses these metrics to ensure your organization's storage is within limits, [salesforce performance is optimized](https://help.salesforce.com/s/articleView?id=000386657\&type=1) and to track overall performance of the GRAX Archives.

To resolve:

* Enable GRAX Auto Fix to allow GRAX to repair any issues with the GRAX Integration User:
  * In the GRAX Application, open the Settings page
  * Expand the "General Settings" Section
  * Edit the "Auto Fix Integration User Permission issues"
  * Select "Fix All Issues" and click "Save"

<figure><img src="/files/mMoJSHazyAKaXdhmtaml" alt="" width="375"><figcaption></figcaption></figure>

* To manually grant GRAX access:
  * In the Salesforce Application, Open "Setup"
  * Use Quick Find to search for "Permission Sets"
  * Find and open the "GRAX Integration User Permission" permission set
  * Use "Find Setting..." to search for "Manage Users"
  * Click the Edit button at the top of the Permissions page
  * Check the box next to "Manage Users"
  * Click "Save"

</details>

<details>

<summary><strong>Can I use the System Administrator profile for the Integration User?</strong></summary>

Yes, but keep in mind that the standard System Administrator profile does not automatically grant full access to all records and fields. Certain permissions, like View Encrypted Data and Query All Files, are not enabled by default, and Field Level Security still applies.

</details>

<details>

<summary><strong>Can I use a custom profile instead of the GRAX permission sets?</strong></summary>

A custom profile can be used alongside the GRAX permission sets, but it cannot replace them. To ensure proper functionality and access control, GRAX permission sets must remain in place.

</details>

<details>

<summary><strong>Can I rename the GRAX permission sets?</strong></summary>

No. Renaming GRAX permission sets can disrupt essential functions like monitoring, alerting, and troubleshooting. It may also affect `Missing Field Permissions` detection and `GRAX Lightning Web Components` (LWCs). To ensure system stability, please refrain from renaming the GRAX permission sets.

</details>

<details>

<summary><strong>What does an error running the Field Level Permission Apex script mean?</strong></summary>

The FLS Apex script needs to list every object, field and field permission in your org and update `FieldPermissions` records for anything missing. This must be run by a System Administrator or else it is likely to encounter an error. For orgs with many objects or many missing field permissions the script may take a while and encounter Apex timeout errors.

If you hit an error with the script, [please open a support ticket](/support/get-support) with these details:

* Subject: FLS Permission Script Errors
* Your Salesforce org ID
* Your Salesforce System Administrator email address
* Details of what script you ran and how
* The full error message you received

</details>

<details>

<summary><strong>What if my permissions were incomplete during Backup?</strong></summary>

To avoid having to redo work due to incomplete permissions, GRAX automatically checks and enforces permissions before you can start Backup. However if a permission problem did affect backup data you can:

1. Fix the permission problem, for example grant missing Field Level Security
2. Browse to /web/tools in the GRAX Application (`Settings` --> `Diagnostics and Tools`)
3. Select the `Reset Backup objects` tool
4. Click on the object that needs to be reset
5. Review the confirmation message
6. Click "Proceed" to reset the object as if it has never been backed up with GRAX
7. Repeat step 4-6 as needed for all affected objects

This is non-destructive, and re-does the object backfill with the correct permissions, "fixing" your backup data set.

</details>

<details>

<summary><strong>What if I can't grant 'View All Data'/'Modify All Data' or remove Field Level Restrictions?</strong></summary>

GRAX goal is to provide the best Recovery Point Objective (RPO) possible. To support data recovery, GRAX must:

* Read **all records and their relationships** frequently for backup
* Write **any record and its relationships** at any time from backup data for restore

If GRAX can not read some objects or records entirely, or some records partially due to field restrictions, its backup data set is incomplete. If GRAX can not write some objects or records entirely, its ability to restore data is incomplete. Therefore, **any permissions that deny access** to read or write any object, record, or field can lead to a total inability to recover data.

The [Create a secure Salesforce API user guide](https://help.salesforce.com/s/articleView?id=000331470\&type=1) specifically calls out "Modify All Data," which implicitly includes "View All Data," as critical for an integration:

> Modify All Data - Specifies that the user can view any data stored in the database and edit any field with the editable flag. This permission is also required for any user who wants to upsert non-unique external IDs through the API. When this permission isn't enabled and if the user tries an upsert using non-unique external ID the error seen is as follows : INSUFFICIENT\_ACCESS: Upsert requires view all data on a non-unique custom index

</details>


# Troubleshooting

This document includes detailed instructions and frequently asked questions to help you troubleshoot your GRAX Application. Click on a link below to be directed to the section of your choice:

* [Frequently Asked Salesforce Questions](#frequently-asked-salesforce-questions)
* [Common Salesforce Errors](#common-salesforce-errors)
* [Troubleshooting Network and Infrastructure Issues](#troubleshooting-network-and-infrastructure-issues)

## Frequently Asked Salesforce Questions

#### Why is the record count I see in GRAX different than the one in Salesforce?

The record count you see in the org setup under "Storage Usage" is an estimate. Same for the [Record Count platform API](https://developer.salesforce.com/docs/atlas.en-us.api_rest.meta/api_rest/resources_record_count.htm).

To get an actual count of records from Salesforce you need to issue a `COUNT` SOQL query, though note it may timeout when there are a lot of records. In this case you may want to issue multiple queries counting records in different time ranges, or use the [Data Loader](https://help.salesforce.com/s/articleView?id=sf.exporting_data.htm\&type=5) to export records IDs and count them from a file instead.

#### How can I see how many records GRAX has in backup? What about how many records were archived?

Just like Salesforce, GRAX stores estimated record counts. This allows this data to be displayed, grouped, and segmented quickly on demand. These estimates are displayed in the Backup and Archive dashboards as well as in GRAX Insights. They can also be queried programmatically via the [Estimated Record Counts API](https://api.grax.com/#tag/records/GET/api/v2/record-counts).

Please note there is a margin of error of approximately 2% for these numbers. They can become outdated if you reset Backup; if this is the case, contact us.

If you need a precise count of records, use [Global Search](/reuse-data/global-search).

#### Does the Salesforce Winter '25 Release Affect the GRAX Application?

No. There should be no effect on any GRAX functionality due to the latest Salesforce release. You can read more about this release [here](https://help.salesforce.com/s/articleView?id=release-notes.salesforce_release_notes.htm\&release=252\&type=5). Additionally, the RFC 7230 Validation for Apex RestResponse Headers that were enforced in Spring '24 will also not impact GRAX.

#### Will the upcoming depreciation of third party cookies for certain browsers affect Salesforce or my GRAX Application?

No. The Cookies Having Independent Partitioned State (CHIPS) change that Google will be making will not have any effect on your GRAX connection in Salesforce or your GRAX Application; you can read more about this [here](https://developers.google.com/privacy-sandbox/3pcd/chips).

#### Does GRAX support Enhanced Domains?

Yes. [Enhanced domains](https://help.salesforce.com/s/articleView?id=sf.domain_name_enhanced.htm\&type=5) meet the latest browser requirements and are now being used in all Salesforce orgs. As long as you're using OAuth to login to your Salesforce environments, the Enhanced Domain Enforcement impact to GRAX is minimal. After making the domain change, you'll need to take the following steps:

* Login to your SFDC environment
* In a separate tab navigate directly to your GRAX Application URL and append /web to the end and select `Sign-in with Salesforce` or `Connect with Auto Config` - if you don't know this URL, you can also navigate to the GRAX Application by clicking on the `Schedule` tab within the GRAX managed package
* Click on the `Allow` button on the Allow Access pop up window if it appears (there are some orgs that do not require this step)

These steps should give you access back to GRAX. Once you have access, double check the Salesforce connection within GRAX (in the `Settings` section) and that the Integration User is connected to confirm the change.

#### Does GRAX support Salesforce Hyperforce?

Yes. [Salesforce Hyperforce](https://www.salesforce.com/products/platform/hyperforce/) is a new architecture that allows customers to run Salesforce applications on public cloud infrastructure providers such as Amazon Web Services (AWS), Google Cloud Platform (GCP), or Microsoft Azure. Hyperforce was announced by Salesforce in December 2020 as part of its Dreamforce event.

The Hyperforce API is the same as the Salesforce API. From a developer's perspective, this means that you can continue to use the Salesforce API to build and customize your applications, and the API remains the same regardless of whether you are running your Salesforce applications on Hyperforce or on Salesforce's own infrastructure.

Therefore GRAX works with Hyperforce deployments with no changes.

If you do use:

* Hyperforce
* GRAX LWC in Apex (non-iframe) mode
* Self-managed GRAX deployment

Your AWS deployment has a Web Application Firewall (WAF), which may block the LWC API requests coming from your Hyperforce Apex servers.

In this case, Salesforce publishes [a list of Hyperforce external IPs](https://compliance.salesforce.com/en/documents/a006e0000121zduAAA) which will need to be allowed to communicate with your GRAX Application.

This configuration is uncommon, and a simpler solution is to use the [GRAX LWC in IFrame mode](/reuse-data/managed-package/first-generation/features#configuration).

#### Does an instance refresh impact my GRAX connection?

No. A Salesforce instance refresh/migration occurs when SFDC upgrades the infrastructure supporting your instance in their data centers. Following this maintenance, your instance will move to a new data center, and the name of your instance will change.

Prior to an instance refresh/maintenance, SFDC will provide customers a date/timeline when the refresh will occur, specifying a maintenance window where their instance will be down. GRAX will be available during this SFDC maintenance period but GRAX will not be able to perform any backup or archive operations until the SFDC org is back up and available.

GRAX uses OAuth to access SFDC, so you may need to reauthorize the integration. Once the instance refresh/migration is complete, you’ll want to re-authenticate the GRAX integration user by navigating to the GRAX Application and logging in with the integration user.

After the integration User has been authenticated, GRAX will resume all activities (backup, archive, etc.) from the point where the service was disrupted.

Please review [SFDC Instance Refresh Maintenance best practices](https://help.salesforce.com/s/articleView?id=000387056\&type=1) for additional information.

#### Does GRAX use Salesforce Platform Events?

No. Salesforce Platform Events don't support all objects needed by GRAX and [Event Allocations](https://developer.salesforce.com/docs/atlas.en-us.platform_events.meta/platform_events/platform_event_limits.htm) are VERY limiting (when backing up ALL objects). Currently, [GRAX Backup](/protect-data/backup) captures [Salesforce objects](/protect-data/backup/supported-objects), [Binary Files](doc:supported-objects#file-objects) (Attachment, Content, Chatter Files, etc), and Salesforce system-tables. Data and binary files MUST be captured at the same rate/time or you risk damaging referential integrity or completeness of data. To fulfill our customers backup needs Salesforce Platform Events aren't an option due to incomplete object support. If you have questions please reach out to the [GRAX team](/support/get-support).

#### Can GRAX be used with Salesforce Shield Platform Encryption?

Yes. [Salesforce.com's Shield Platform Encryption](https://help.salesforce.com/s/articleView?id=sf.security_pe_overview.htm\&type=5) should not impact your ability to use GRAX, as GRAX is designed to work seamlessly with Salesforce's native encryption.

Salesforce provides various encryption options for data at rest and in transit, such as Shield Platform Encryption and Transport Layer Security (TLS). These encryption options are designed to protect data from unauthorized access and breaches, but they do not affect the functionality of third-party applications like GRAX. You can encrypt certain fields on standard and custom objects, data in Chatter, and search index files. With some exceptions, encrypted fields work normally throughout the Salesforce user interface, business processes, and APIs.

GRAX operates through the Salesforce API, which allows it to access data regardless of whether it is encrypted or not. GRAX creates backups of your data, and these backups are stored in a separate, encrypted data store. When you need to restore data, GRAX decrypts the backup and restores it to Salesforce.

*Helpful Links*

* [GRAX Compliance](https://documentation.grax.com/security/)
* [Salesforce Shield Platform Encryption](https://help.salesforce.com/s/articleView?id=sf.security_pe_overview.htm\&type=5)
* [What You Can Encrypt](https://help.salesforce.com/s/articleView?id=sf.security_pe_encryptable_data.htm\&type=5)
* Try out Shield Platform Encryption at no charge in a [Salesforce Developer Edition orgs](https://developer.salesforce.com/signup).

#### Does GRAX support Salesforce Private Connect?

Yes. [Salesforce Private Connect](https://help.salesforce.com/s/articleView?id=sf.private_connect_overview.htm\&type=5) routes SFDC traffic via Salesforce-managed public cloud VPCs instead of letting egress traffic cross the public internet. This is a network-layer configuration; if configured correctly, the GRAX Application won't be able to tell the difference between a public or private connection. GRAX isn't responsible for configuring or maintaining Private Connect. Private Connect requires additional Salesforce licensing. Private Connect is only available for self-managed GRAX deployments.

#### Will the ICU Locale format update impact my GRAX Application?

No. For orgs created after Winter 2020, the [ICU Locale format](https://help.salesforce.com/s/articleView?id=sf.icu_migration_enable.htm\&type=5) is enabled by default. The transition to the ICU Locale format will not impact your GRAX Application.

#### Can I use GRAX to decommission a Salesforce org?

Yes. Your company may have Salesforce orgs that you no longer want to maintain after a consolidation, merger, or business reorganization. GRAX makes it easy to protect this data, search, and reuse it without paying Salesforce to keep the org active. After disconnecting from Salesforce, the backup of your data remains safe with GRAX and accessible through powerful tools including Global Search. Record data can be exported to CSV and Data Lake may be used to send a copy of data to your downstream systems such as your data lake or analytics tools.

#### How do I set up GRAX and decommission a Salesforce Org?

1. First, you will need a GRAX license. Please contact your account manager or GRAX Sales.
2. Next, you will need to set up a GRAX deployment and connect a storage bucket as described in the [Platform documentation](https://documentation.grax.com/platform/).
3. Then, you will [connect to your Salesforce org](/other/settings/connecting-salesforce) using an account that has the Salesforce Administrator role and run GRAX `Auto Config`. This will assign the [GRAX Integration User](/other/permissions-and-access/integration-user) permission sets for the GRAX Application to operate.
4. Once the App is connected, log in with Salesforce OAuth and enable Backup if it is not yet running. Backup will automatically run as it protects all of your data. Note: There can be a backlog of data to synchronize when you initially connect to a Salesforce Org, and you will notice the [backup status](/protect-data/backup) noted as "backfilling" as this process is catching up.
5. Once Backup is complete, you can disconnect your Salesforce org, but first you will need to create a local user account via email and password to log in as GRAX will no longer have access to Salesforce OAuth to provide authentication. This can be done under Settings -> User Management in the GRAX Application. Your password link will be sent via email. Note that [GRAX Support](/support/get-support) will need to enable this feature on your org.
6. Now you can safely decommission your Salesforce Org.

   > Note that any changes to data in the Salesforce org made after disconnecting GRAX will no longer be captured by GRAX Backup.

### Common Salesforce Errors

{% hint style="info" %}
For Sandbox Seeding, the errors will need to be resolved in the seeding target org unless otherwise specified
{% endhint %}

#### What does `CANNOT_EXECUTE_FLOW_TRIGGER` or `CANNOT_INSERT_UPDATE_ACTIVATE_ENTITY` mean?

Your Salesforce org has a trigger interfering with record creation or deletion.

**Apex CPU time limit exceeded**

*Example:* `CANNOT_INSERT_UPDATE_ACTIVATE_ENTITY: EmailMessageTrigger: System.LimitException: Apex CPU time limit exceeded`

The Apex code in this trigger is taking too long to run on a record and failing with a `System.LimitException` error due to a SFDC platform time limit. The Salesforce platform enforces that Apex code from triggers must run within a short amount of time to prevent excessive resource consumption. Possible options to resolve this are:

* Use the `Disable automations` option in the seeding job to disable the trigger for the duration of the seeding job (Sandbox Seeding only)
* Modify the trigger to not run for the GRAX integration user
* Optimize the trigger code to run in less time

**General Trigger Execution**

*Example:* `CANNOT_INSERT_UPDATE_ACTIVATE_ENTITY: TaskTrigger: execution of AfterInsert`

The code in the trigger is blocking the operation based on how the object or related objects are currently configured. Possible options to resolve this are:

* Add an override to the job to set the field value that will allow the record to pass the trigger validation rule (Sandbox Seeding or Restore)
* Use the `Disable automations` option in the job to disable the trigger for the duration of the seeding job (Sandbox Seeding only)
* Modify the trigger to not run for the GRAX integration user
* Review the trigger code to allow the operation to succeed

#### What does `DUPLICATE_VALUE` or `DUPLICATES_DETECTED` mean?

*Example:* `DUPLICATE_VALUE: A topic with the name, why-GRAX-is-amazing, already exists.`

Salesforce requires unique values for certain fields (such as topic names) and GRAX has tried to insert a duplicate.

* For Sandbox Seeding, this can happen when re-seeding a dataset without undoing the previous seed first. Undo the previous seed that included this record or select a different dataset to seed.
* For Restore, this can happen if a record you are trying to restore was previously un-deleted from the Salesforce Recycle bin. To ensure data integrity and records are properly linked, always restore records from GRAX.

#### What does `ENTITY_IS_DELETED` mean?

*Example:* `ENTITY_IS_DELETED: entity is deleted`

The record was deleted in Salesforce since the last backup was taken. Wait for the next Backup to complete and try the activity again.

#### What does `FIELD_CUSTOM_VALIDATION_EXCEPTION` mean?

*Example:* `FIELD_CUSTOM_VALIDATION_EXCEPTION: Activity can't be created for Closed enquiry. Please Re Open Enquiry to save Activity.`

The `FIELD_CUSTOM_VALIDATION_EXCEPTION` error indicates that there is a custom validation rule or trigger on the object that is blocking the record from being created. Review the message details to determine the cause, possible options to resolve this are:

* Add an override to the seeding job to set the field value that will allow the record to pass the validation rule (Sandbox Seeding or Restore)
* Use the `Disable automations` option in the seeding job to disable the trigger for the duration of the seeding job (Sandbox Seeding only)
* Modify the validation rule / trigger to not run for the GRAX integration user
* Skip the object

#### What does `INACTIVE_OWNER_OR_USER` mean?

*Example:* `INACTIVE_OWNER_OR_USER: The specified user is inactive`

The GRAX integration user does not have sufficient permissions to create the records for inactive users. Please review the permissions for the GRAX integration user / GRAX integration user permission set and ensure it has the `Set Inactive Owners` permission. See the [Restore Best Practices](/protect-data/restore/restore-best-practices) page.

#### What does `INSUFFICIENT_ACCESS_OR_READONLY` mean?

**Can't create a link for Email Message when it's not in draft state**

*Example:* `INSUFFICIENT_ACCESS_OR_READONLY: You can't create a link for Email Message when it's not in draft state (field=LinkedEntityId)`

When a ContentDocumentLink attached to an EmailMessage is deleted, there are some guards that prevent us from placing it back. Salesforce only allows links to emails that are either in state draft, or created with `IsClientManaged` set to true.

If none of these apply, our recommended workaround is to archive the email message and then restore it using GRAX. In this process we're going to set that `IsClientManaged` flag, and then restore ContentDocumentLinks related to it.

**Insufficient access rights on object id or record type**

*Example:* `INSUFFICIENT_ACCESS_OR_READONLY: insufficient access rights on object id` or `INSUFFICIENT_ACCESS_OR_READONLY: invalid record type`

The GRAX integration user does not have sufficient permissions to delete / create this object or record type. Please review the permissions for the GRAX integration user / GRAX integration user permission set and ensure it has correct object and record type access.

**Invalid sharing type**

*Example:* `INSUFFICIENT_ACCESS_OR_READONLY: Invalid sharing type V (field=ShareType)`

You are trying to seed or restore a Content Document (ContentVersion + ContentDocumentLink) and you are getting an "Invalid sharing type V" error message. To resolve it, you need to configure file sharing to `Set by Record` in your Salesforce org settings:

1. Go to `Setup` and enter `Files` in the `Quick Find` box.
2. Under `Salesforce Files`, choose `General Settings`.
3. Enable the `Set by Record` option for files attached to records.

Additional [documentation](https://help.salesforce.com/s/articleView?id=release-notes.rn_files_sharing_set_by_record.htm\&type=5\&release=222) is available from Salesforce.

**Data Validation rules**

There is a validation rule that is blocking the record from being created as it currently exists.

* Review the message details to determine the cause and options to resolve by setting an override (such as setting the `state` field to `Draft` for the example above)
* Skip the object.

**Insufficient permissions**

The GRAX integration user does not have sufficient permissions to create the record. Review the permissions for the GRAX integration user / GRAX integration user permission set and ensure it has access to create the records for that object

#### What does `INVALID_CROSS_REFERENCE_KEY` or `INSUFFICIENT_ACCESS_ON_CROSS_REFERENCE_ENTITY` mean?

*Example:* `INVALID_CROSS_REFERENCE_KEY: Missing reference: field TaskId ref ID: 00T46000008US01AAG`

When Salesforce needs to do a many-to-many link between two objects (such as Accounts can have many tasks, task can be linked to many accounts), it uses a junction object called a cross-reference. This error means that the cross-reference GRAX is trying to create is missing or unable to access one side of the junction. This most commonly has two likely causes:

1. `Missing reference` - One of the 2 records that are being linked is missing:
   * Check to see if there are other errors in the job that may indicate the record was skipped
   * The record was manually excluded
   * The record was not included in the job due to a filter such as max children
2. `this ID value isn't valid for the user` or `You do not have the level of access necessary` - The GRAX integration user doesn't have sufficient permissions to create the cross-reference record type. Check the permissions for the GRAX integration user / GRAX integration user permission set and ensure it has access to create the cross-reference record type.

#### What does `INVALID_OR_NULL_FOR_RESTRICTED_PICKLIST` mean?

*Example:* `INVALID_OR_NULL_FOR_RESTRICTED_PICKLIST: bad value for restricted picklist field: Direct_Traffic (field=originalSource)`

The picklist value GRAX is trying to set is not a valid value for the field. This can happen if the option was deleted since the record was backed up or in Sandbox seeding if the option was added to the source org after the target org was created. Possible options to resolve this are:

* Add the missing picklist value to the picklist options for the field
* Add an override to the job to set the field value to a valid picklist option

#### What does `STORAGE_LIMIT_EXCEEDED` mean?

*Example:* `STORAGE_LIMIT_EXCEEDED: storage limit exceeded`

Your Salesforce target org does not have sufficient storage space to load the data you are trying to seed. GRAX provides an estimated size for all records vs the available space reported by the seeding target. Since these are estimates, its possible to exceed the available space when the data is actually loaded. Please edit the seeding job and reduce the amount of data being seeded, some options are:

* Reduce file size by skipping the `ContentDocument` or `Attachment` objects
* Skip objects that are not meaningful to the use cases for the seeded data. For example running a test on `Opportunity` data doesn't require `EmailMessages`
* Clicking on the Object in the graph or list will show you the estimated size of the records for that object. You can use this to determine which objects are consuming the most space and use this info to decide which objects to skip

#### What does `UNABLE_TO_LOCK_ROW` mean?

*Example:* `UNABLE_TO_LOCK_ROW: unable to obtain exclusive access to this record or 10 records: ...`

Salesforce is attempting to update a separate record based on the changes to the record that reported this error while a different record in the same batch is also updating that record. This can happen as a result of a roll-up summary field or a trigger, such as rolling up the number of opportunities on an account. If you're seeing this error, it means the Salesforce and GRAX ROW LOCK resolution processes were unable to separate the child records that are blocking each other.

* Review the trigger logic to ensure it can properly handle batches of records (and doesn't assume only one record will be updated at a time)
* For Sandbox Seeding, reduce the number of records being seeded
* For Restore, retry the restore job for the failed records

#### What does `UNKNOWN_EXCEPTION` mean?

`UNKNOWN_EXCEPTION` is a catch-all for errors that Salesforce does not provide a specific error code for. The error message usually has a general description of the cause of the error. Search the internet or contact Salesforce support to help identify the root cause. Based on the cause of the error, it may be possible to correct it by setting an override or skipping the object.

### Troubleshooting Network and Infrastructure Issues

This section covers issues blocking general operations of GRAX including networking failures, boot failures, restart behaviors, etc. This guide includes commands specific to the Amazon Linux 2 AMI maintained by AWS, but attempts to remain otherwise infrastructure-agnostic where possible. *Some steps may not work as intended if you have made heavy customizations to networking, image, or environment.*

#### Where are GRAX files located?

First, let's note the locations of the GRAX binary and environment file. Keeping track of their paths helps validate service configurations in later steps. In a typical installation, GRAX is stored under `/home/ec2-user/graxinc/grax` and the `.env` file is stored under `/home/ec2-user`. Thus, we'll use the following paths:

* GRAX binary: `/home/ec2-user/graxinc/grax/grax`
* GRAX command-line tools: `/home/ec2-user/graxinc/grax/graxctl`
* Environment file: `/home/ec2-user/.env`

#### Is GRAX executable?

To ensure that Linux knows GRAX is an executable, we can check permissions on the file as follows:

```bash
[root@grax-test-runtime grax]# ls -la
total 278108
drwxr-xr-x 2 root root      137 Aug 20 10:09 .
drwxr-xr-x 3 root root       18 Aug 18 12:38 ..
-rwxr-xr-x 1 root root 71471248 Aug 20 10:09 grax
-rwxr-xr-x 1 root root 56687264 Aug 19 15:48 graxctl
-rw-r--r-- 1 root root 52411443 Aug 18 12:39 master.zip
```

The "x" in the permissions strings at the beginning of each line denotes an executable file. If the `grax` and `graxctl` files aren't executable, we can mark them as such:

```bash
[root@grax-test-runtime grax]# chmod +x grax graxctl
```

#### How should the Environment file be formatted?

There are several important rules to remember for `.env` files:

1. Only one key-value pair per line
2. Only `=` is supported as a key-value separator
3. Comments aren't supported

Comments are the most commonly seen issue as teams often attempt to label values for later reference. Unfortunately, this causes most `.env` parsers to immediately return (sometimes non-fatally). This can lead to partial configurations and thus cause indeterminate symptoms.

For a total example of a valid `.env` file, see our [Linux Install Guide](/infrastructure/install-guides/install-on-linux).

#### Is the service (systemd) working properly?

This guide assumes you're operating GRAX as a permanent service on the instance with `systemd`. The most common issues with `systemd` are configuration issues in the service file. In a typical installation, the GRAX service file is at the path `/lib/systemd/system/grax.service`.

**Validate Configuration**

We can see the contents of the service configuration by using `cat`:

```bash
[root@grax-test-runtime grax]# cat /lib/systemd/system/grax.service
[Install]
WantedBy=multi-user.target
[Service]
EnvironmentFile=/home/ec2-user/.env
ExecStart=/home/ec2-user/graxinc/grax/grax
Restart=always
Type=simple
[Unit]
Description=grax daemon
```

Check the following:

1. `EnvironmentFile` is a valid absolute path that points to your GRAX `.env` file.
2. `ExecStart` is a valid absolute path that points to your GRAX executable.
3. `Restart` is "always" to ensure GRAX is always running regardless of exit-singaling.

**Service Status**

The services run via `systemd` are managed and interacted with via the `systemctl` command. To see the current status of the GRAX service, we can use the `status` subcommand:

```bash
[root@grax-test-runtime grax]# systemctl status grax.service
● grax.service - grax daemon
   Loaded: loaded (/usr/lib/systemd/system/grax.service; enabled; vendor preset: disabled)
   Active: active (running) since Fri 2022-08-19 17:35:29 UTC; 5 days ago
 Main PID: 13125 (grax)
   CGroup: /system.slice/grax.service
           └─13125 /home/ec2-user/graxinc/grax/grax

(Log Lines omitted for brevity)

Hint: Some lines were ellipsized, use -l to show in full.
```

We always expect the GRAX service to be "active" unless under maintenance or GRAX was intentionally taken offline. If the service isn't "active" (that is "failed" or "stopped"), you can restart GRAX at any time by running the `restart` subcommand:

```bash
[root@grax-test-runtime grax]# systemctl restart grax.service
```

If the GRAX service is entirely disabled, you can enable it with the `enable` subcommand, and then enforce a start immediately with `start`:

```bash
[root@grax-test-runtime grax]# systemctl enable grax.service; systemctl start grax.service
```

A successful start of the service (and thus app) outputs logs in the app log file. If you have a regular health check configured, you'll see logs in relation to those calls being submitted to the log if the app is active.

#### Is the Web Server Serving Requests?

GRAX is a web server and API. It offers an endpoint for an external health check to see if the app is available. The health check endpoint for GRAX is an HTTP/1.1 HTTPS-only GET handler on `/health`. In a typical installation, GRAX runs on port 8000.

We can manually check the status of the app from the instance by curling the local route:

```bash
[root@grax-test-runtime grax]# curl -k https://localhost:8000/health
ok
```

The expected value from the endpoint HTTP status 200; this signifies a healthy service. A failed call, either via timeout, rejection, or different status is a sign of a failed service/app. This endpoint is designed for load balancer registration and de-registration, not for instance replacement.

#### Is Connectivity intact?

The GRAX Application is a data-processor at its core. To process data, it must be able to retrieve that data, write it to storage, and read it back. When you add app maintenance, licensing, and telemetry to the equation, connectivity is critical to ensure proper operation.

Only some pieces of overall connectivity requirements are possible to test from the instance. These are the egress connections that are used to push or pull data to/from remote resources. Ingress communications, as they start from other sources, are harder to test.

Timeouts, rejections, or broken connections during the following tests are considered failures. All failures should be investigated.

**GRAX HQ**

Communication to GRAX HQ is egress-only, and can be tested relatively simply. To start, we can verify connectivity to the GRAX packaging API, which allows downloading of the app in the first place:

```bash
[root@grax-test-runtime grax]# curl -L -o testgrax https://hq.grax.com/api/v2/download/graxinc/grax/master/linux/amd64
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100    68  100    68    0     0   4270      0 --:--:-- --:--:-- --:--:--  4533
100 48.6M    0 48.6M    0     0  6344k      0 --:--:--  0:00:07 --:--:-- 9270k
```

The `-L` flag is utilized to follow the ALB redirect that points to HQ. `-o` is used to avoid printing the binary data to the terminal. A successful download of several dozen MB can be considered a passing test.

Next, let's confirm POST requests to HQ succeed:

```bash
[root@grax-test-runtime grax]# curl -L -X POST https://hq.grax.com/api/v2/dd/logs/api/v2/logs
{"cause":"","status":401,"message":"Unauthorized"}
```

This may seem an unusual result, but the 401 return is a good enough response to know that your POST request made it to HQ without requiring you construct a valid set of credentials for a simple test. If you don't get a JSON response in line with the above, consider the test a failure.

**Salesforce**

To read and write Salesforce data via the Salesforce API, GRAX must first be able to connect. We can test that connectivity much the same as above:

```bash
[root@grax-test-runtime grax]# curl https://test.salesforce.com
```

The response to the above should be an HTML document, too large to post here. Repeat that test for the following:

1. `https://login.salesforce.com`
2. Any custom/my-domain paths configured in your organization

**Postgres**

To test connectivity to your DB instance, we use `postgresql`, a Linux command-line tool that allows direct interaction with Postgres clusters. Installing the tool may be unnecessary depending on image, but can easily be done like the following:

```bash
[root@grax-test-runtime grax]# yum install postgresql
Loaded plugins: extras_suggestions, langpacks, priorities, update-motd
amzn2-core                                                                                                                                                                           | 3.7 kB  00:00:00
amzn2extra-docker                                                                                                                                                                    | 3.0 kB  00:00:00
Package postgresql-9.2.24-6.amzn2.x86_64 already installed and latest version
Nothing to do
```

As you can see, our typical installation already includes the right tooling. We can connect in two ways:

1. Copy the `DATABASE_URL` value from your `.env` file, and run `psql [database_url]`
2. Use the `graxctl psql` subcommand

A valid connection results in an interactive `psql` shell, which can be exited with `\q`:

```bash
[root@grax-test-runtime grax]# ./graxctl psql
2022/08/25 16:25:54 trace C9tATg        VBlnGV start main mainWithCode:152 e=0s
2022/08/25 16:25:54 pprof addr: [::]:46569
2022/08/25 16:25:54 trace C9tATg        VBlnGV info  config setTemplateDefaults:427 msg="loading general template v1.0.0 defaults" template=virtual-appliance e=0s
2022/08/25 16:25:54 trace C9tATg        VBlnGV info  config/secrets New:175 secretStore=database e=11ms

psql (9.2.24, server 14.5)
WARNING: psql version 9.2, server version 14.0.
         Some psql features might not work.
SSL connection (cipher: ECDHE-RSA-AES256-GCM-SHA384, bits: 256)
Type "help" for help.

grax=> \q
```

If a connection cannot be made, `graxctl` tries again every 5 seconds for a few minutes. This is usually a sign of the following:

1. `DATABASE_URL` isn't set
2. `DATABASE_URL` isn't properly formatted
3. `DATABASE_URL` contains invalid cluster name
4. `DATABASE_URL` contains a password with special characters that need to be escaped
5. `DATABASE_URL` isn't exported to current environment
6. Route tables are forcing DB traffic outside of the VPC
7. Security groups aren't allowing traffic from the Instance into the DB

If a connection can be made but you receive a Postgres error about DB existence, credentials, etc., then you likely have an issue with correctness in your `DATABASE_URL` value (that is username, password, or DB name).

#### *Is additional assistance available?*

If you have exhausted the steps here and require further assistance (or have recommendations for quality/completeness of this guide), contact [GRAX Support](/support/get-support).


# Debugging Salesforce Triggers

Salesforce Triggers within customer orgs can cause issues with Archive and Restore functionality for a number of reasons. Triggers represent arbitrary code execution in the midst of GRAX interacting with data; their effects can be unpredictable and destabilizing. This document provides guidance on how to debug Triggers that may be causing issues with GRAX.

## When to Debug Triggers

Debugging of Triggers may become necessary when:

* Archive or Restore jobs are failing due to Apex CPU timeouts.
* Archive or Restore jobs are failing due to Apex governor limits.
* Archive or Restore jobs are failing due to unhandled exceptions in Apex code.
* Archive or Restore jobs are failing due to integrity/validation errors on unrelated records/objects.

## How to Debug Triggers

Trace Flags are the most powerful tool for debugging triggers. They allow you to review the execution of your code after the fact at a low level, and can be used to identify the root cause of issues including where in the Trigger code the problem is occurring. For information on how to set a Trace Flag for a given user, class, or trigger, see the [related Salesforce documentation](https://help.salesforce.com/s/articleView?id=sf.code_add_users_debug_log.htm\&type=5).

Note the following:

* Most triggers and automation in Salesforce run in "System Mode" and will not be affected by Trace Flags scoped to the user that triggers the operation. To capture logs for these automated operations, you must set a Trace Flag for the System user. See below for more information.
* Class and Trigger flags only override user-scoped flags, if set, and will not enable logging on their own. Enable flagging for the user in question first.
* Trace Flags are not retroactive. They must be set before the code is executed to capture the log.
* Trace Flags are not permanent. Ensure that your flags have not expired when reproducing issues to avoid missing logs.

## Debugging System Mode Operations

To debug operations that run in System Mode, you must set a Trace Flag for the System user. The System user does not show up in the Salesforce GUI in any context, meaning the API must be used to set the Trace Flag. The following steps outline how to set a Trace Flag for the System user:

1. Use the Salesforce Developer Console to query for the System user ID. The System user's "name" is always 'System': `SELECT Id FROM User WHERE Name = 'System'`.
2. Use the Salesforce Developer Console (in "Tooling API" mode) to query for the Debug Level ID you wish to use: `SELECT Id, DeveloperName FROM DebugLevel`. The lowest possible level of logging is recommended.
3. Use Workbench to set a "USER\_DEBUG" trace flag for the System user. Documentation on this process can be found [here](https://help.salesforce.com/s/articleView?id=000386565\&type=1).

## Support for Triggers

GRAX Support cannot directly support the debugging, interpretation, or modification of Customer triggers or automation unrelated to GRAX products. If you require assistance with debugging your triggers beyond the information above, please consult with your Salesforce Administrator and Developer resources, then reach out to Salesforce's Customer Support team for further assistance. If you require assistance related to the GRAX product, please [reach out to GRAX Support](/support/get-support).


# Preparing GRAX for a Salesforce Org Decommission

Access your Salesforce data post salesforce org decommission using GRAX

Your company may have Salesforce orgs that you no longer want to maintain after a consolidation, merger, or business reorganization. GRAX makes it easy to protect this data, search, and reuse it without paying Salesforce to keep the org active.

After disconnecting from Salesforce, the backup of your data remains safe with GRAX and accessible through powerful tools including Global Search.

### Before you Begin <a href="#prerequisites" id="prerequisites"></a>

The following must be in place before proceeding with decommissioning:

* GRAX is [connected to Salesforce](https://documentation.grax.com/other/settings/connecting-salesforce) and [storage is configured](https://documentation.grax.com/other/settings/connecting-storage)
* [GRAX Backup](https://documentation.grax.com/protect-data/backup#how-do-i-enable-it) is current. Verify by reviewing the Safe Up To date/time on the Backup Dashboard.
* At least one local GRAX user has been created (see below)
* *(Optional)* Ensure all desired objects are enabled on [Data Lake](https://documentation.grax.com/reuse-data/data-lake)

### **Step 1: Create Local Users**

Once Backup is up to date, the first step prior to decommissioning your Salesforce Org is to create a [local user](https://documentation.grax.com/other/permissions-and-access/local-users) within your GRAX app. This allows simple login access via email and password, as GRAX will no longer have access to Salesforce OAuth to provide authentication.

**Best Practices for Local Users**

* Create at least **two admin users** to prevent lockout scenarios
* Document local user credentials in a secure password manager
* Ensure passwords are set to **never expire** for long-term disconnected deployments
* Optionally, create local users for key stakeholders who may need data access

Once the prerequisites are met and a local user is created, please contact [GRAX Support](https://documentation.grax.com/support/get-support) to verify all is set prior to safely decommissioning your Salesforce Org. GRAX Support will help by giving the green light to this transition and enable **Decommission Mode** for your GRAX app.

### Step 2: Contact GRAX Support

Once your backup is current and local users are created, contact GRAX Support before proceeding. Support will:

* Verify your backup state and local user configuration
* Confirm Data Lake and any other dependencies are in order
* Enable **Decommission Mode** for your GRAX app

{% hint style="warning" %}
Note that any changes to data in the Salesforce org made after disconnecting GRAX will no longer be captured by GRAX Backup. Ensure all desired data has been backed up before proceeding.
{% endhint %}

### Navigating your GRAX app in Decommissioned Mode

Once GRAX is placed in a Decommissioned Mode by GRAX Support, the app operates as a standalone application for accessing historical data. The GRAX app remains largely the same, but features that rely on a live Salesforce connection are disabled.

**Supported Features in Disconnected Mode:**

* [**Global Search**](https://documentation.grax.com/reuse-data/global-search): Search and view historical backed up data
* [**Sandbox Seeding**](https://documentation.grax.com/reuse-data/sandbox-seeding): Seed historical data to a connected Salesforce org (requires additional configuration)
* [**Purge**](https://documentation.grax.com/protect-data/purge): Manage the permanent deletion of data from the GRAX Data Vault

**Features not Supported in Disconnected Mode:**

* Any features requiring Salesforce API access
  * Auto Backup
  * Archive
  * Restore
* Data Lake

{% hint style="info" %}
Data already delivered to your Data Lake remains intact and accessible there. No new data will be sent after decommissioning.
{% endhint %}

<figure><img src="/files/k65ZH0F5xCgF4XyB7xlr" alt=""><figcaption></figcaption></figure>

**(Optional) Deactivate Salesforce Integration User**

Once you have confirmed Decommission Mode is working as expected and you have successfully logged in with a local user, you may deactivate the GRAX integration user in Salesforce or delete the connected app. This step is not required, but is recommended if you are fully retiring the org.


# Auto Updates

{% hint style="danger" %}
*This feature cannot be disabled.*
{% endhint %}

GRAX releases security, performance patches, bug fixes, and feature improvements multiple times a day on average. With automatic software updates, GRAX updates itself to the latest safe and tested release every weekday so that you never have to deal with the frustration of running into an already known and fixed bug or being told to "update and try again" by GRAX Support.

{% hint style="warning" %}
On platforms like Heroku or Docker, applications can be configured in such a way that they always boot from a pre-selected image or slug. In these cases, if GRAX updates itself on disk, the latest version is newer than that of the slug. GRAX's internal schema management is such that reverting to old versions may prove fatal to an app and require manual intervention. Updating on boot helps prevent this issue, always keeping the code on the latest release. If this update fails on boot, the app won't be allowed to boot to an old version.
{% endhint %}

## Overview

The GRAX Application checks in with `hq.grax.com` every weekday to verify the latest version. If a newer version than the local code exists, the app downloads the latest version and install it in place over the previous version. It then restarts the app in place. The data operations (backup, archive, restore) of the app, if running, won't be harmed by these restarts or downloads. The app resumes processing tasks when it comes back online.

The app also performs a version and update check on every boot to avoid accidentally reverting to older versions. See note above about slug-based platforms.

## Frequently Asked Questions

#### Can I manually update?

Yes; the General Settings page contains a manual "Update Now" button. When pressed, the GRAX Application performs version checks against `hq.grax.com` and replaces the running app if necessary.

#### Can I control the update schedule?

You can not customize the update schedule or perform an unattended software rollback.

Weekday auto updates are the primary mechanism for GRAX to maintain, improve and monitor production service reliability, performance and security over time.

GRAX has many internal mechanisms in place to make sure updates work:

* Internal Continuous Integration (CI) practices to detect issues during development
* Proactive monitoring and alerting around all live customer environments
* Quick deploy capabilities for emergency security and reliability fixes
* Internal root cause analysis and remediation tracking for all customer facing production incidents

This eliminates the need for customers to manage update schedules, maintenance windows, and perform upgrades themselves.

#### Can I control what version of GRAX is running in a self-managed deployment?

Self-Managed GRAX deployments offer total control over where your data goes, as well as who has access to the infrastructure.

It does not, however, offer total control over the GRAX software. GRAX Inc., maintains control over its own internal development, testing and release process like all third party software and service providers.

Previous versions of GRAX required manual operations to update the backend software. This control left many customers running a significantly out of date product. One of the top shared concerns was that production environments didn't get critical security and reliability updates in a timely fashion. Another common occurrence was that customers would open support cases for issues that have long been resolved.

We found that across the customer base, manual updates effectively meant no updates, with most customer environments falling 30, 60, 90+ days behind. Catching up required scheduling lengthy maintenance windows, running manual database migrations and data back-fills, and re-training on 3 months of product changes at once.

Auto Updates has alleviated all of these problems, keeping everything up to date with the latest security patches and improvements. Just like your web browser and other software services.

The major tradeoff is that it offers customers less control over the frequency of production changes. However, if an update does introduce a regression or unwanted change, it greatly increases the speed at which we find and correct problems.

#### What if an update breaks GRAX?

If your production GRAX environment is completely offline to login or to make backups, start by opening a "Critical Production Issue" on <https://www.grax.com/help/>. This opens a priority support case for GRAX to track the problem to resolution.

GRAX's proactive monitoring and alerting means that GRAX also rapidly detects production problems and should be able to root cause, develop a fix, and update an environment without any customer action if it is a release defect.

While you are waiting for a response from GRAX support and your next automatic update, we recommend you review your own infrastructure logs and metrics to determine if there are underlying infrastructure issues that could cause the problem, like a full disk or database in read-only mode.

#### Where can I find additional information?

GRAX recommends [*Accelerate: The Science of Lean Software and DevOps: Building and Scaling High Performing Technology Organizations*](https://en.wikipedia.org/wiki/Accelerate_\(book\)) as scientific study on how faster and more frequent deploys lead to higher reliability.


# Support

Regardless of deployment model, the GRAX Support team provides app-level support to all customers as part of their contract. This support is intended to resolve product failures, close knowledge gaps, and ensure your success as you adopt the product. Support SLAs depend on the severity of the reported issue. A first response to customer issues is sent within the applicable SLA time frame. In this context, a “First Response” means an acknowledgment to the customer that the support request has been received by the support team.

Support availability is during non-[US holiday](https://www.opm.gov/policy-data-oversight/pay-leave/federal-holidays/#url=Overview) business hours, Monday through Friday (9 AM - 6 PM EST).

Users can submit cases over the in-app support form or via email. GRAX uses commercially reasonable efforts to respond to and resolve each case. Actual resolution time depends on the nature of the case and the resolution. A resolution may consist of a fix, workaround, or other solution in GRAX's reasonable determination.

## How to Get Help

* Explore our detailed [documentation](https://documentation.grax.com/), including our [Troubleshooting](/other/troubleshooting) article
* Create a ticket in the [`Get Support`](/support/get-support) tab within GRAX
* Email [GRAX Support](mailto:help@grax.com)

## Supported Requests

* Repeated backup failures
* Archive failures
* Restore failures
* Data discrepancies
* Questions about new features
* Issues managing permissions
* Application outage troubleshooting
* Contractual clarifications

The GRAX Support team also assists you throughout the lifetime of your GRAX contract to ensure you remain up to date with latest releases. This means they help update both the GRAX Managed Package in Salesforce as well as the GRAX backend if so allowed/requested/needed. They also contact you occasionally about deprecations, best practices, or known issues.

## Unsupported Requests

Whether you are installed on the standard GRAX AWS Marketplace templates or custom built your own GRAX infrastructure, GRAX won't support any of the infrastructure components directly. Network failures, domain registration lapses, storage capacity issues, component failures, and improper configuration of the compute resources which prevent software operation aren't the responsibility of GRAX.

If a support ticket is submitted and the issue is decidedly outside the GRAX Application itself, GRAX support relays the necessary information. At this point, it's your team's responsibility to resolve the underlying infrastructure issues.

## Customer Planned Maintenance Support Requirement

\
If GRAX Support needs to be available during a Customer planned maintenance window, that maintenance window must fall within the support hours associated with their purchased support plan (Standard or Premium Support). Requests for support outside the entitled support window may not be accommodated unless otherwise agreed upon in advance.\
Examples of planned maintenance windows include, but are not limited to:

* Salesforce seasonal releases
* Infrastructure upgrades&#x20;
* Software updates
* Scheduled application downtime for internal system changes

Please [submit a case](#how-to-get-help) to request Support.&#x20;

## Support SLA

### Standard Support Response Times & Availability

{% hint style="info" %}
Access to Technical Support during 9-6 EST, US Business Days (excluding company holidays)&#x20;
{% endhint %}

| Severity | Priority                           | First Response    | Availability                      |
| -------- | ---------------------------------- | ----------------- | --------------------------------- |
| 1        | Critical Production Issues         | 4 Business Hours  | 9 AM - 6 PM EST, US Business Days |
| 2        | Non-Critical Production Issues     | 12 Business Hours | 9 AM - 6 PM EST, US Business Days |
| 3        | Questions or Non-Production Issues | 24 Business Hours | 9 AM - 6 PM EST, US Business Days |

{% hint style="warning" %}
Standard Support requests received after business hours (9-6 EST) are addressed the following business day
{% endhint %}

### Premium Support Response Times & Availability

{% hint style="info" %}
Access to Technical Support 24 hours a day, 7 days a week, 365 days a year
{% endhint %}

| Severity | Priority                           | First Response    | Availability         |
| -------- | ---------------------------------- | ----------------- | -------------------- |
| 1        | Critical Production Issues         | 2 Calendar Hours  | 24/7 365 days a year |
| 2        | Non-Critical Production Issues     | 6 Calendar Hours  | 24/7 365 days a year |
| 3        | Questions or Non-Production Issues | 12 Calendar Hours | 24/7 365 days a year |

### Priority Definitions

| Severity | Priority                           | Definition                                                                                                                                                                              |
| -------- | ---------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| 1        | Critical Production Issues         | A business-stopping emergency caused by a complete loss of GRAX service or major feature degradation, resulting in a mission-critical production failure. Issue is in a production org. |
| 2        | Non-Critical Production Issues     | Production issues that don't affect general business operations. Issue is in a production org.                                                                                          |
| 3        | Questions or Non-Production Issues | General questions, non-production issues, or support requests. Issue is in a sandbox.                                                                                                   |

## Issue resolution standards

#### Critical Production Issue (Sev 1)

A business-stopping emergency caused by a complete loss of GRAX service or major feature degradation, resulting in a mission-critical production failure.

* Response time: Requires email ticket - response time based upon email receipt; however, GRAX team can provide troubleshooting via bridge assistance no sooner than the stated minimum response time frame.
* Resolution: Actual resolution time depends on the nature of the case and the resolution. A resolution may consist of a fix, workaround, software update, or other solution in GRAX's reasonable determination.

**Root Cause Analysis (Sev 1)**

GRAX doesn't commit to the completion of a root cause analysis (RCA) sooner than 15 days after a given incident or sooner than 7 days after one is requested.

**Data Correction (Sev 1)**

If possible, GRAX takes all commercially reasonable measures to correct data affected by production issues.

**Workaround Technique (Sev 1)**

If possible, GRAX provides reasonable alternative methods of operation until issues are resolved.

#### Non-Critical Production Issue (Sev 2)

Production issues that don't impede critical processes.

* Response times: requires email ticket - response time based upon email receipt
* Resolution time: Actual resolution time depends on the nature of the case and the resolution. A resolution may consist of a fix, workaround, software update, or other solution in GRAX's reasonable determination.

**Data Correction (Sev 2)**

If possible, GRAX takes all commercially reasonable measures to correct data affected by production issues.

**Workaround Technique (Sev 2)**

If possible, GRAX provides reasonable alternative methods of operation until issues are resolved.

#### Non-Production Issue / Question (Sev 3)

General questions, non-production issues, or support requests.

* Response time: requires email ticket - response time based upon email receipt
* Resolution time: Actual resolution time depends on the nature of the case and the resolution. A resolution may consist of a fix, workaround, software update, or other solution in GRAX's reasonable determination.

**Workaround Technique (Sev 3)**

If possible, GRAX provides reasonable alternative methods of operation until issues are resolved.

## Additional Information

### Assistance

GRAX must be able to reproduce errors to resolve them. Customer agrees to assist and work closely with GRAX to reproduce errors, including conducting diagnostic or troubleshooting activities as requested and appropriate. Also, depending on Customer's approval on a case-by-case basis, Customers may be asked to provide remote access to their app environment.

### Language

Support is available only in English.

### Exclusions

Assistance with other AppExchange applications (installs/uninstalls/customization).

Assistance with non-GRAX products, services or technologies, including implementation, administration or use of third-party enabling technologies such as databases, computer networks or communications systems.

Assistance with installation or configuration of hardware including computers, hard drives, networks, or printers.

Assistance with the implementation or system administration of Salesforce.com, permission and access policies, data manipulation (de-duping, merging, cleansing), Visualforce, and custom Apex code.

GRAX isn't responsible for any outage to the extent resulting from the following which would not be included in the calculation of the “Qualifying Outage Minutes”:

* (A) Periods of Scheduled Downtime.
* (B) Outage due to system administration, commands, file transfers performed by the Customer outside published guidelines.
* (C) Force Majeure events.
* (D) Other outages due to inability of the user to access the internet or Supplier site, where inability to access the site isn't the result of a failure by Supplier or its site.
* (E) Outages due to instability or unavailability of Customer-provided infrastructure.
* (F) Outages due to changes in Customer-owned infrastructure that have a direct impact on GRAX products.

### Notification and Reporting Standards

Formal Problem Response Communication

* (A) System Outage: Customer is notified within a commercially reasonable time frame of a system outage or failure.
* (B) Compromised Data: Customer is notified within 72 hrs upon determination of an actual security breach or if Customer’s data has been compromised.
* (C) System Change: System changes are made available to the Customer on the [GRAX Documentation hub](/notices) within seven (7) business days of the release of the revised system.

### Maintenance

GRAX maintenance includes product upgrades and updates as needed. During the upgrade/update process GRAX Technical Support is available for any questions or concerns. If there is a new feature or UI/UX component change, training is provided through live demos or documentation.

### Monitoring

GRAX shall use such measurement and monitoring tools and procedures as are required to properly measure and report performance of the Cloud Services against the applicable Service Levels. GRAX may use its reasonable discretion in selecting the tools and procedures used in measuring and monitoring performance, provided such tools and procedures sufficiently enable GRAX's compliance with the above.

### System availability

GRAX uses commercially reasonable efforts to make the online Services available 24 hours a day, 7 days a week, except for: (a) planned downtime (of which GRAX shall give advance electronic notice as provided in the Documentation), and (b) any unavailability caused by circumstances beyond our reasonable control, including, for example, an act of God, act of government, flood, fire, earthquake, civil unrest, act of terror, strike or other labor problem (other than one involving our employees), internet service provider failure or delay, Non-GRAX Application, or denial of service attack. GRAX is dependent on AWS and Salesforce.com system availability and isn't responsible for any issues resulting from those systems not being available.

### Credits

GRAX won't provide credits or off-sets. GRAX shall rectify any defect within a commercially reasonable period.


# Get Support

We highly recommend that customers submit support requests via the GRAX Application by clicking `Get Support` on the left hand side navigation menu of the GRAX Application. This streamlines your support requests so that our support team can effectively monitor, prioritize, and address your questions according to the details captured on the form and not an unstructured email. In combination with [Session Monitoring](/support/record-session-activity), our teams have quicker and better insight into your support request while reducing the need to send multiple emails as we collect details of your request.

## Submit a New Ticket

Click the `Get Support` tab on the GRAX Application then select the `Enable Diagnostic Reporting` option to record GRAX Application sessions. You can now record the steps you take to recreate the issue. This allows a detailed recreation of GRAX Application issues without the need to get on a call with GRAX Support. You can also manually enable session recordings by going to the `Settings` Tab and click `Enable for 90 Minutes` link on the `Record Session Activity/Content` row for GRAX Support section.

![Get Support Recording Popup](/files/DS9GfRuoQn4BC7N8jlr1)

Once you have recorded the steps to reproduced the issue, navigate back to and click the `Get Support` tab again to end the recording session and submit the support request.

![Get Support Submission Popup](/files/6kYfv7KKFD4Df9NV2sIM)

If you've finished your recording session or have a different issue, `click here` to summit the new support request.

!["Create a Ticket" Form](/files/Bg77hBfC591YOoihmmn3)

Your support request is submitted and awaiting acknowledgement. A GRAX Support representative reviews your request as soon as possible and provides a first response. A first response to support issues must be sent within the applicable SLA time frame. In this context, a `First Response` means an acknowledgment to you that the support request has been received by the support team. See [Application Support SLAs](/support)

{% hint style="info" %}
The recorded sessions cannot be accessed within the GRAX Application and are accessible by GRAX engineers only.
{% endhint %}

## Find Your GRAX Version

There are two different versions used to describe any given GRAX environment. First, the GRAX backend/Application version identifies the code running in the environment. Second, the GRAX Managed Package has its own versioning within the Salesforce release system. Finding these version numbers can prove critical to the GRAX support process. Here's how you can do that.

### GRAX Backend / Application Version

Finding the version of your GRAX is simple, as it's displayed on every Application page.

If you're not logged in, navigate to `https://[yourgraxappdomain]/web` and look below the login form:

![GRAX Version on Login Page](/files/yTTusDE2hkFrFbGnL4jF)

If logged in, navigate to any major page in the GRAX Application, and look in the bottom left corner:

![GRAX Version on App Pages](/files/73FEXR76j7IEAp3GR86E)

### GRAX Managed Package Version

Salesforce has great documentation on how to find information about your installed packages. To learn more, see their [related documentation](https://help.salesforce.com/s/articleView?id=sf.distribution_package_detail.htm\&type=5). When reporting the package version to GRAX, please send the `Package Version` value.

## Grant GRAX Support Access to your Application

The `GRAX Support Access` feature allows Application access to be granted to GRAX support personnel. This allows our team to view your application behavior and settings directly, reducing troubleshooting time and providing a faster solution.

To grant access to GRAX Support:

* Navigate to the `Settings` tab of the GRAX Application
* Expand the `General Settings` section
* Scroll down to the `Allow GRAX Support Access` section and click the pencil icon
* Choose how long you'd like access to be granted by selecting an option from the drop-down menu
* Click `Save`

This access can be revoked at any time by clicking the pencil icon, selecting `Do not allow`, and then clicking `Save`.


# Record Session Activity

The GRAX Application lets users record their sessions on demand, enabling Support to review actions leading to errors without a live call. This helps prevent miscommunication and allows engineers to better assist by viewing exact steps and errors. Recordings are saved for later review and aren’t monitored in real time.

## Steps for Recording Session Activity

* Navigate to the `Settings` tab of the GRAX Application
* Open the `General Settings` sub-tab
* Click `Enable for 90 Minutes` to the right of the `Record Session Activity/Content for GRAX Support`

<figure><img src="/files/K7uWXHCdFc63B2Wdt3e2" alt=""><figcaption></figcaption></figure>

* Walkthrough the steps  that were taken and led up to the error
* Once complete, click the `STOP` button in the upper-right corner of the yellow banner displayed at the top of the GRAX Application

## Frequently Asked Questions

### When should I enable monitoring?

GRAX Support may request permission to record your session activity to help reproduce errors and resolve issues more quickly. If you encounter an issue within the GRAX Application, please follow the steps above to allow for session recording. Be sure to note the approximate time  (including timezone)  that you clicked the `Enable for 90 Minutes` button in your support ticket.

### When does GRAX record sessions?

The GRAX Application records session activity only when manually enabled. Session recording is temporary, and GRAX cannot activate monitoring remotely for users.

### What data is included in session recordings?

While monitoring sessions, the GRAX Application automatically hides data-containing fields - excluding IDs - so record data, filenames, file sizes, and record names aren’t captured. GRAX engineers cannot view this data during reviews. Only the session of the user who enabled monitoring is recorded; other users’ sessions are excluded. Recorded data is encrypted, accessible only to GRAX employees, and deleted after 30 days.

### How do I know when GRAX is recording a session?

A non-dismissible banner appears at the top of the GRAX window when a session is being recorded. If the banner isn’t visible, GRAX is not recording any activity.

![Banner Example](/files/X8t7GF6WeLGQj4yinulN)

### How do I disable session monitoring?

To disable Monitoring before the 90-minute limit, click the `STOP` button located in the upper-right corner of the yellow banner at the top of the GRAX Application. This will immediately stop the session recording.


# Platform Basics

The GRAX Platform serves as a central hub for deploying, managing, and monitoring GRAX Applications and their underlying infrastructure across multiple clouds. Each GRAX "deployment" is a self-contained infrastructure stack entirely isolated from all others. This section will cover the following topics:

1. Logging in
2. Creating a Team
3. Connecting a cloud account
4. Deploying a GRAX Application
5. Accessing a GRAX Application
6. Deleting a GRAX Application

## Logging in

To log in to the GRAX Platform, navigate to [the Platform](https://platform.grax.com) and choose a Social Sign-on method or create a new account. You can use your Salesforce, Google, or Microsoft account to log in to avoid managing a separate set of credentials. Keep in mind that each Salesforce user in each independent Salesforce org is a separate user so logging in with your user from one org is different from logging in with your user from another org.

![Platform Login](/files/1iDvpqLXETG89DlJfza2)

## Creating a Team

By default, all Platform users are on a "personal team." This team is created when you sign up and can be used just like any other including inviting other users to it. However, if you're part of a larger organization, you may want to create a new team with an appropriate name to manage your GRAX deployments. To create a new team, click on the "Teams" dropdown in the lower left-hand corner and then click "Create New Team" at the bottom of the list. Fill out the form with your team's name and click "Save."

![New Team](/files/nDviNm4c2KaAsSK8QtYK)

## Connecting a Cloud Account

{% hint style="info" %}
This step is not necessary if you only wish to deploy a GRAX trial.
{% endhint %}

Deploying a GRAX Application via Platform also deploys the underlying infrastructure to the target cloud environment. Accordingly, you must connect a cloud account to the GRAX Platform with the necessary privileges to create and maintain the [infrastructure stack](/infrastructure/architecture/architecture) and the required [storage resources](/infrastructure/other/blob-storage). This account must remain connected to the GRAX Platform throughout the lifetime of the deployment as GRAX manages updates, upkeep, and patching for the environment.

To connect a cloud account, click on the "Connections" option in the navigation menu and then select the "Connect" button for your provider of choice.

For AWS, reference the separate [AWS Connection documentation](/platform/connections/aws-connection).

For Azure, reference the separate [Azure Connection documentation](/platform/connections/azure-connection).

For Heroku, reference the separate [Heroku Connection documentation](/platform/connections/heroku-connection).

## Deploying a GRAX Application

To deploy a GRAX Application, click on the "Deployments" option in the navigation menu and then click the "New Deployment" button in the top right corner. Choose the deployment type that best suits your use case and cloud expertise. If you've selected a deployment type that requires a cloud account but such a connection does not exist, you will be prompted to connect your account. Once you have a valid connection, click "Create Deployment" to begin the deployment process.

![Platform New AWS Deployment](/files/S4w8E7JIU6GldukvUW3i)

By default, all teams are allowed to provision a single GRAX Trial deployment. The infrastructure resources for Trials are deployed to a GRAX-owned cloud account and are intended only for use as a trial run of the GRAX Application. All Trials are automatically deleted after 7 days, data included; GRAX Archive is not available during Trials to avoid data loss. If you deploy any other deployments, the Trial option will no longer appear for your team.

![Platform New Trial Deployment](/files/sPdWf5IF6AN8W245WYGO)

{% hint style="info" %}
For GRAX Cloud deployments in a new Team with no connections, contact GRAX Support to have the team configured for GRAX Cloud.
{% endhint %}

Regardless of deployment method or cloud account, deployment will take roughly 15 minutes.

## Accessing a GRAX Application

Once the deployment is complete, the deployment will be listed as "Running" on the "Deployments" list. Click the "Open" button to launch the new application in another tab or "Details" to see infrastructure status and options for configuration. Once deployment is complete for each application, all configuration for that application's Backup, Archive, Restore, and other features will be done within the application itself. The deployed application is isolated from the GRAX Platform and all other GRAX applications.

![Platform Deployment List](/files/Qgd1ofbpiAbZZhLvNOY3)

GRAX manages the domain name and ingress configuration for each deployment. All deployments will be provisioned a unique domain name under `*.secure.grax.io` that is accessible via HTTPS. Domain names for GRAX apps can be customized upon request, but this requires DNS changes for whichever domain you would like to use. WAF and other security configurations can also be customized upon request (depending on availability).

## Deleting a GRAX Application

If you no longer have any need for a GRAX Application, it can be deleted in the GRAX Platform via the "Danger Zone" on the "Details" page. After manually confirming the deployment name and team, submit the delete form to start the de-provisioning process. Once the deployment is de-provisioned, all data and resources associated with the deployment are destroyed and cannot be recovered. Deleting a deployment can take 15-20 minutes, after which it will disappear from your deployments list.

![Platform Destroy Deployment](/files/Bd7Blr0xIe3Q2sUbLqA1)


# Platform Connections

## What Does GRAX Use the Platform Connection for?

GRAX uses the access granted to your Cloud Platform to manage your deployment of the GRAX Application; This responsibility includes creation, monitoring, and maintenance of the infrastructure. As GRAX launches new features and cloud platforms release new versions of resources, GRAX will apply necessary infrastructure updates and improvements to bring you the most cost effective and secure deployment possible.

The specific resources needed by the GRAX Application varies by Cloud Platform and will change over time as those platforms update their offerings and features are added to the GRAX Application. For example resources, you can review our [Architecture Documentation](/infrastructure/architecture/architecture) and suggestions on account auditing are discussed [here](#how-can-i-audit-graxs-cross-account-access).

## What are the benefits of GRAX Managed Deployments?

Compare the security profile and total cost of ownership (TCO) of these two options:

* a system configured and updated with machine-to-machine automation
* a system that requires direct access by many people or teams to set up and update

The former requires 0 people in the process, takes 30 minutes for the initial set up, and is automatically updated with security improvements over the entire lifetime of the system.

The latter can take many people weeks in the initial process to set up and weeks again to find the right people to perform security updates. It adds new risks of many people having access and passwords to systems, making configuration mistakes, and delaying security updates.

Multiply this by every additional system you create to backup additional sandbox and production environments and every security update required over the years of maintaining a system; you'll see that the security profile is significantly higher and the TCO is significantly lower by automating everything.

GRAX maintains isolated accounts with cross-account automation for all "GRAX Cloud" environments, and recommends the same exact security best practices and service to self-managed customers.

## Do you require Administrator (AWS) or Owner (Azure) permissions?

To create and continually manage deployments, GRAX requests a high level of continual access to cloud providers.

Creating resources and automatically updating resources for maintenance, security, and architecture improvements requires a high level of permission. Granting cloud platform managed policies like Administrator and Owner roles are the most straightforward way to guarantee everything works continually and allows GRAX to administer your deployment with minimal and manual intervention by your Operations teams.

But all permissions are ultimately in your control. If you no longer wish GRAX to have access to the Cloud account dedicated to the GRAX Application, the associated roles and principals can be destroyed. However, GRAX cannot manage your deployment by providing support, patching, updates, improvements, or monitoring for infrastructure deployed in Cloud environments that we do not have access to or to which access was prevented for an extended period of time, even if access is restored.

If your security policies don't allow cross-account access or require permissions that are not suitable to create and update GRAX resources, self-managed deployments do not require granting any access to GRAX.

## What are the security implications of GRAX's cross-account access?

At GRAX, information security is job number one. We have designed security into every layer of our product and system management. Cross-account access, combined with fully automated system setup and updates, provides the best security for all our customers and their sensitive data. GRAX uses the following best security practices:

### **Isolation starting at the Account Layer**

Account isolation eliminates the risk of GRAX systems accessing other systems and data and vice-versa. GRAX requires that you run in an isolated account. Our certified templates provide further isolation at the VPC, EC2, database, and storage layers.

### **Automation to setup and manage systems**

Automation eliminates configuration mistakes on first setup and enables fast delivery of updates for critical security improvements.

Automation removes people from the process; people are prone to make configuration mistakes and can be slow to apply security updates. Configuration mistakes and running outdated components are in the [top 10 application security risks](https://owasp.org/www-project-top-ten/).

GRAX utilizes Terraform for the deployment of all infrastructure. The Terraform modules are available on request for review.

### **Password-less IAM roles**

Password-less roles eliminate the risk of leaking credentials and guarantee only authorized machines have access to systems and leave an audit trail.

This eliminates static credentials that can leak and need to be rotated. It improves the ability to audit, where any access to your account other than the GRAX role, and any access to your bucket other than the GRAX Instance role, can trigger security review.

### How can I audit GRAX's cross-account access?

All cross account API calls are logged by AWS to [CloudTrail](https://docs.aws.amazon.com/awscloudtrail/latest/userguide/cloudtrail-user-guide.html). These logs always include the Role ARN and required Role Session Name, both of which include "GRAX". With the cross-account role, anything other than the GRAX role in CloudTrail logs is suspicious.

You can set up [CloudWatch alarms for CloudTrail events](https://docs.aws.amazon.com/awscloudtrail/latest/userguide/cloudwatch-alarms-for-cloudtrail.html) to filter events and send notifications when anything other than the expected roles access your systems.

### How can I update a Platform connection with new credentials?

{% hint style="danger" %}
Before proceeding, confirm that the credentials you are adding to Platform are for the same cloud account and have full access to manage (Create, Update, Destroy) any Cloud resources deployed with the current credentials.
{% endhint %}

1. [Log in](/platform#logging-in) to [Platform](https://platform.grax.com/)
2. In the lower left corner, select the team configured with the existing connection
3. Select "Connections" from the left-hand menu
4. Delete the existing connection
   1\.

   ```
   <figure><img src="/files/7WYoZ3TnRhOlnDmjfoPA" alt=""><figcaption></figcaption></figure>
   ```
5. Click the appropriate button to [connect](/platform#connecting-a-cloud-account) your cloud account with your new credentials:
   1\.

   ```
   <figure><img src="/files/g35P9qgALX0jugP72WMZ" alt=""><figcaption></figcaption></figure>
   ```

### Can I remove GRAX's cross-account access?

GRAX always leaves you in total control. At any time you can remove the cross-account role with the IAM Delete Role operation. Removal of GRAX's access to manage your applications and infrastructure constitutes a termination of GRAX's responsibility to manage, patch, upgrade, and monitor your deployment. If you remove GRAX's access, you are responsible for the security and maintenance of your deployment as well as all future upgrades. GRAX does not guarantee that a deployment can be restored to a managed state after access has been removed for any period of time.

If GRAX discovers that access has been removed, GRAX will notify the applicable application owners repeatedly over a reasonable period, but has no means to restore access independently.


# AWS Connection

GRAX Managed Deployments require a cross-account IAM role with the permissions to create and manage the GRAX Application's infrastructure in a dedicated AWS Cloud account. You can create this IAM role automatically with GRAX's IAM Quick Deploy or manually create the required IAM role.

![New AWS Connection](/files/AueIaGSLA2TDIpCYGb2o)

**External ID:** A Unique ID generated by GRAX for this connection which is used when creating the IAM role's Trust Policy See this [AWS documentation](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_common-scenarios_third-party.html) for details.

**Role ARN:** The [Amazon Resource Name](https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_identifiers.html) for the cross-account IAM role you are providing to GRAX.

## AWS IAM Quick Deploy

Ensure you are logged into your dedicated AWS account on another tab and click the "IAM Role Quick Deploy" button. GRAX will create a CloudFormation stack for an IAM cross-account role with the required permissions.

1. Ensure you are logged into the target AWS account with an Admin level user or a user with access to create IAM cross-account roles.
2. Click the IAM role Quick Deploy button. GRAX will open AWS in a new tab and load our certified [CloudFormation template](https://s3.amazonaws.com/grax-public-templates/master/cloudformation/grax-role.yml) for the cross-account IAM role.
3. Deploy the stack by clicking "Create Stack" in the lower right corner. You can also preview the IAM role and associated policies by creating a change set prior to creating the stack.
4. After you create the stack or execute the change set, click on the Resources tab in the stack to view progress. After a few minutes the AssumeRole resource will have a status of CREATE\_COMPLETE. You may need to refresh the page.
5. Click on the link for `grax-platform` in the Physical ID column to open the newly created role.
6. Copy the ARN value from this page and paste it into the ARN role field in GRAX Platform.
7. Click Save in GRAX Platform.

## AWS IAM Manual Creation

While our Quick Deploy process is highly recommended, your AWS Administrator can manually create the IAM role for GRAX if they choose to do so. The IAM role must have the following:

* Trust Policy allowing `sts:AssumeRole` to GRAX AWS Account 999875163122.
  * A Trust Policy condition limiting to the External ID (copied from the Platform Connection referenced above) is highly recommended.
* Permission to Create, List, and Delete all the necessary GRAX infrastructure.
  * The AdministratorAccess policy is the most straightforward way to accomplish this.

{% hint style="warning" %}
GRAX Support cannot provide assistance with AWS IAM roles not created from our [CloudFormation template](https://s3.amazonaws.com/grax-public-templates/master/cloudformation/grax-role.yml).
{% endhint %}

Our Platform Connections [documentation](/platform/connections/platform-connections) reviews GRAX Security practices and goes into more detail on best practices for this configuration.


# Azure Connection

Setting up an Azure Service Principal is required to allow GRAX to manage infrastructure in your Azure account. This involves a few more steps than the AWS setup, but those steps are outlined below for both the Azure Portal and the Azure CLI.

## Azure Portal (GUI)

### Create the Service Principal

1. Navigate to the [Azure Portal](https://portal.azure.com/) and login with a user that has the necessary permissions to create service principals.
2. Search for and open the `App Registration` service.

   ![App Registrations](/files/NkuxkVTixJk6oPkiEHES)
3. Click `New registration`.

   ![New App Registration](/files/5nrNYTKBcWvPZ5Cyz9zx)
4. Name the team 'GRAX' or something similar in accordance with your business' naming conventions and click `Register`.
5. Copy the `Application (client) ID` and `Directory (tenant) ID` values from the Overview page to a safe location for later use.

   ![App Registration Overview](/files/CDAK196rznBUxNmwRipz)

### Create the Client Secret

1. Open the Service Principal you just created in the Azure Portal.
2. Click `Certificates & secrets`.
3. Click `New client secret`.
4. Name the secret 'GRAX' or something similar in accordance with your business' naming conventions.
5. Copy the `Value` of the secret to a safe location for later use.

### Assign the Service Principal a Role

1. Navigate to the subscription you wish to deploy GRAX into.
2. Click `Access control (IAM)`.
3. Click `Add role assignment`.

   ![Access Control (IAM)](/files/XNim7wTY3PrWtNrVl8ly)
4. Select the `Owner` role under `Privileged administrator roles`.

   ![Select Role](/files/5Xt6CqpGMi8tKD5nbu0k)
5. Click the `Members` tab then search for and select the Service Principal you created earlier.

   ![Select Member](/files/gEa3KgAR1Drt3vNgdIs3)
6. Use the `Review + assign` tab to save the role assignment.

### Configuring the Connection in GRAX

On the GRAX Platform team you'd like to use for creating a deployment, navigate to the `Connections` tab and click `Connect Azure`. Fill in the following values:

* `Tenant ID`: Use the `Directory (tenant) ID` value from the App Registration.
* `Subscription ID`: Use the subscription ID of the Azure subscription you wish to deploy into.
* `Client ID`: Use the `Application (client) ID` value from the App Registration.
* `Client Secret`: Use the `Value` of the client secret you created.

Click `Save` to save the connection.

## Azure CLI (`az`)

### Create a Service Principal

First, ensure that you are logged in:

```bash
az login
```

```json
[
  {
    "cloudName": "AzureCloud",
    "id": "subscrip-abcd-abcd-abcd-abcdabcdabcd",
    "isDefault": "true",
    "name": "Pay-As-You-Go",
    "state": "Enabled",
    "tenantId": "tenantab-abcd-abcd-abcd-abcdabcdabcd",
    "user": {
      "name": "john@example.com",
      "type": "user"
    }
  }
]
```

*Note: In the above JSON, id represents your Azure subscription id.*

Next, set your active subscription:

```bash
az account set --subscription="${id}"
```

Then, create a Service Principal to allow GRAX to manage infrastructure:

```bash
az ad sp create-for-rbac -n "GRAX" --scopes "/subscriptions/${id}" --role "Owner"
```

This returns the required authorization data for your Service Principal, as JSON.

```json
{
  "appId": "appidabc-abcd-efgh-abcd-efgh-abcdabcdabcd",
  "displayName": "John",
  "name": "http://example.com",
  "password": "password-abcd-efgh-abcd-efgh-abcdabcdabcd",
  "tenant": "tenantid-abcd-efgh-abcd-efgh-abcdabcdabcd"
}
```

Now you need to enter the following values into your Azure Connection details:

1. Click [Add Azure Connection](https://platform.grax.com/connections/new/azure).
2. Fill the values as follows:
   1. `Tenant ID`: Use the `"tenant"` value from the JSON.
   2. `Subscription ID`: This is your Azure subscription id.
   3. `Client ID`: Use the `"appId"` value from the JSON.
   4. `Client Secret`: Use the `"password"` value from the JSON.
3. Click `Save`


# Heroku Connection

Providing a Heroku API key and configuring storage is all that is required to manage a GRAX deployment in your Heroku account.

## Heroku Portal

1. Navigate to the [Heroku Dashboard](https://www.heroku.com) and login with a user that has the necessary access to the team that will be used to host the GRAX deployment.
2. Click on the profile in the upper right corner and choose "Account Settings"

   ![Account Settings](/files/ZYTyrU30AMF8XSYRZBaD)
3. Scroll down to the section titled "API Key"

   ![API Key](/files/vFTn2miE95zTscfJzKvf)
4. Click `Reveal`
5. Copy the API key

## Configuring the Connection in GRAX

On the GRAX Platform team you'd like to use for creating a deployment, navigate to the `Connections` tab and click `Connect Heroku`. Fill in the following values:

* `API Key`: Use the API key from the Heroku Dashboard

Click `Save` to save the connection.

![New Heroku Connection](/files/1MhKANbeS2Qvv4psM57S)

## Deployment Configuration

Once a Heroku Account has been connected a Deployment can be created.  Navigate to the `Deployments` tab and click `New Deployment`. In the Advanced Settings, fill in the Heroku Team and Space names:

* `Enterprise Team Name`: enter the Heroku Team Name
* `Enterprise Space Name`: enter the Heroku Space Name

Click `Save` to create the deployment.

<figure><img src="/files/OtNSKKK9Glmwa1zyHYI5" alt=""><figcaption><p>New Heroku Deployment</p></figcaption></figure>


# Install on Heroku

Heroku is a PaaS (Platform as a Service) that allows you to deploy applications without worrying about the underlying infrastructure.

The trial installation includes all of the resources needed to enable GRAX backups and the GRAX datalake.

If you are new to GRAX, we recommend starting with the trial as you can always upgrade and migrate resources and data later.

If you are setting up GRAX for production, we recommend deploying GRAX to Heroku [via the GRAX Platform](/platform/connections/heroku-connection).

## Trial Installation

To quickly and easily deploy a GRAX trial on Heroku click the "Deploy to Heroku" button below:

[![Deploy to Heroku](https://www.herokucdn.com/deploy/button.png)](https://www.heroku.com/deploy/?template=https://github.com/graxinc/grax-heroku-v2/tree/main)

This will provision the following resources:

1. A Heroku dyno with the GRAX Application
2. A Heroku Postgresql Add-on for GRAX Application state
3. An S3 Storage Add-on for CRM data
4. A GRAX Add-on to setup the datalake

![Heroku button resources](/files/ldy6xpXCqTBzdtfp9RQi)

## Maintenance

The GRAX Application installed on Heroku takes advantage of GRAX's automatic update tools, meaning that it automatically updates to the latest version of GRAX every day. This ensures that you always have the latest features and bug fixes without needing to manually update the application. Short of configuration changes or database maintenance, you should not need to interact with the Heroku application directly.

## Accessing the Application

By default, Heroku applications generate a random URL at which the application will be hosted. This can be discovered by clicking the "Open App" button on the Heroku application's dashboard. If you are interested in setting up a custom domain, this can be accomplished via the Heroku application's "settings" page whenever you'd like.


# Install on Linux

{% hint style="warning" %}
This guide is written with RHEL or Amazon Linux 2023 in mind. If you are running a different distribution of Linux, steps may vary.
{% endhint %}

This guide walks through installing GRAX from scratch natively on a Linux operating system. It configures a service to automatically restart GRAX if it fails, and creates a rsyslog helper service to copy logs from stdout to a log retention file. **If you do not have infrastructure set up to run GRAX, see our** [**technical requirements**](/infrastructure/requirements/technical-requirements) **and** [**architecture guides**](/infrastructure/architecture/aws-architecture-example) **for more information first.**

{% hint style="danger" %}
**Never set up a publicly accessible copy of the GRAX Application without modifying the ADMIN\_PASSWORD in the configuration or removing it entirely.**
{% endhint %}

## Installation Steps

Before you begin the steps below, many of them require root access. Start by logging in as root or elevating your session to a point where you have `sudo` capabilities.

### Download and Expand GRAX Executable

To download the GRAX Application, download the proper build from GRAX HQ for your architecture. Builds are only available for Linux running on ARM64 and AMD64 architectures. The following example determines which of the builds to download based on the architecture of a supported machine:

```bash
$ CPU=$(uname -m); case "$CPU" in x86_64) CPU="amd64" ;; aarch64) CPU="arm64" ;; esac
$ curl https://hq.grax.com/api/v2/download/graxinc/grax/main/linux/$CPU -L --output grax.zip

  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100    67  100    67    0     0    740      0 --:--:-- --:--:-- --:--:--   797
100 47.5M    0 47.5M    0     0  5738k      0 --:--:--  0:00:08 --:--:-- 7915k
```

GRAX HQ serves this download in a compressed format, meaning you need to expand it to get the contained binaries:

```bash
$ unzip grax.zip

Archive:  grax.zip
  inflating: grax
  inflating: graxctl
```

Mark the resultant files executable for later use:

```bash
$ chmod +x grax graxctl

[no output expected]
```

### Create a Configuration File

Create a configuration file with a valid `key=value` list. The GRAX Application loads configuration values from the environment at time of boot; to use this configuration, the values must be loaded into the execution environment prior to calling the GRAX binary. Normally, this is done via the `EnvironmentFile` argument of a systemd service configuration. As a result of using such a tool to load the file into the environment, the name and location of this file is arbitrary. We specify a `.env` file located in the app directory as an example below.

The configuration file includes your server's public domain name (`WEB_APP_URL`). In some cases, this domain name is of the format `https://grax.department.customer.com`, but can be decided by your networking team. The app's port is also adjustable via `ADDR`, but keep in mind that a change here may result in necessary changes in your load balancers, security groups, and/or monitoring.

**Generate a secure random value for each of the values marked \[GENERATE] below.** A length of at least 30 characters each is recommended. You can generate such a value with `openssl rand -base64 48 | tr "+/" "-_" | tr -d =` in most Linux distributions.

```bash
$ vim .env

ADDR=:8000
SELFSIGNEDCERT=1
DATABASE_URL=postgres://username:password@clusteraddress.com:5432/database-name
WEB_APP_URL=https://grax.department.customer.com
SECRET_STORE_BASE=[GENERATE]
ADMIN_PASSWORD=[GENERATE]
GRAX_REGISTRATION_KEY=[OPTIONAL - OMIT UNLESS PROVIDED BY GRAX SUPPORT]
```

`SELFSIGNEDCERT` is only required in cases where you wish to terminate TLS at a Load Balancer or gateway, but still encrypt the traffic between the Load Balancer and the GRAX Application. This is not required if you are using custom certificates installed on the machine.

If your disk configuration dictates that GRAX cache data in a location other than your OS-default `TMPDIR` (usually `/tmp`), you can override that value by adding `TMPDIR=/new/path` to the above. For more information, see [here](/infrastructure/requirements/technical-requirements#compute).

### Create a GRAX Service Configuration

Use systemd to ensure GRAX stays running as a background service.

```bash
$ cat <<EOT >> /lib/systemd/system/grax.service
[Install]
WantedBy=multi-user.target
[Service]
User=ec2-user
Group=ec2-user
EnvironmentFile=/home/ec2-user/.env
ExecStart=/home/ec2-user/grax
Restart=always
RestartSec=30s
StartLimitInterval=0
StartLimitBurst=0
Type=simple
MemoryHigh=80%
MemoryMax=90%
[Unit]
Description=grax daemon
EOT
```

This service configuration assumes standard file locations on Amazon Linux 2023 and runs GRAX as the standard EC2 user. If you are running on a different distribution or as a different user, adjust the paths and user/group accordingly.

### Logging (Optional)

By default, systemd writes the `stdout` and `stderr` streams from services to the journal, accessible with `journalctl`. The journal automatically handles log retention to ensure that disk space does not fill up, but GRAX logs may be co-mingled in the journal with other services making them harder to consume. To separate GRAX logs into a dedicated file, you can use `rsyslog` to copy the logs from the journal to a file. This can often make integrations with third party monitoring tools or log aggregators easier.

First, create the `rsyslog` configuration to read `grax` service output from the journal and write it to `/var/log/grax.log`:

```bash
$ cat <<EOT >> /etc/rsyslog.d/grax.conf
$umask 0000
$FileCreateMode 0644
:programname, isequal, "grax" /var/log/grax.log
& stop
EOT
```

Next, create a `logrotate` configuration to rotate the log file daily and keep only 7 days of logs:

```bash
$ cat <<EOT >> /etc/logrotate.d/grax
 /var/log/grax.log
{
  missingok
  daily
  copytruncate
  rotate 7
}
EOT
```

### Start all the Services in Order

The services defined above, and the configurations that control them, need to be started/restarted to operate as intended after the updates:

```bash
$ systemctl daemon-reload && systemctl restart rsyslog.service && systemctl enable --now grax.service
```

The services should now be online and logs should be written to `/var/log/grax.log` shortly.

## Next Steps

To proceed with connecting GRAX to Salesforce and your storage platform of choice, start with our [connection documentation](/other/settings/connecting-salesforce).


# Install on Docker Desktop

## Installation Steps

### Setup Docker Desktop

First download, install, and run [Docker Desktop](https://www.docker.com/products/docker-desktop/).

### Get a GRAX Trial Key

Next, sign into the [GRAX Platform](https://platform.grax.com) and get a registration key.

Go to "Backends," then "New," then "GRAX for Docker Desktop," then "Create Key." You can then see a "Registration Key" in your list of backends. This key can only be activated once.

### Download and Configure GRAX Docker Compose Files

Download [GRAX Docker Compose Files](https://s3.amazonaws.com/grax-public-templates/master/docker/docker.zip), unzip them, and configure it with your registration key.

```bash
export GRAX_REGISTRATION_KEY=<Paste from GRAX Platform>
```

```bash
curl -L -o docker.zip https://s3.amazonaws.com/grax-public-templates/master/docker/docker.zip
unzip docker.zip
cd docker
echo "GRAX_REGISTRATION_KEY=$GRAX_REGISTRATION_KEY" >> .env
```

### Start Up GRAX with Docker Compose

```bash
docker-compose up -d
```

After 30 seconds, GRAX is running alongside a database and storage service. You can go to the "Backend URL" from [GRAX Platform](https://platform.grax.com), e.g:

* <https://comfortable-trade-78.secure.grax.io>

You can pause GRAX with:

```bash
docker-compose stop
```

And resume again with `docker-compose up -d`.

## Resetting Everything

{% hint style="warning" %}
The following deletes all data in the object storage and database and releases the URL you used to access GRAX on your laptop. This can not be undone.
{% endhint %}

You can destroy all Docker resources with:

```bash
docker-compose down
docker rm -f $(docker ps -a -q) || true
docker image rm -f docker-grax || true
docker volume rm $(docker volume ls -q) || true
```

Then, sign into the [GRAX Platform](https://platform.grax.com), go to "Backends," and "Delete" your previously activated backend and registration key.


# Technical Requirements

## What You Need to Bring

GRAX requires network accessibility (domain and certificate), compute resources, a PostgreSQL database, and a storage bucket at a bare-minimum.

### Network Accessibility

Your GRAX service must either be reachable publicly via a registered domain name with a valid certificate or via a Salesforce-configured VPN connection to your private network.

GRAX offers subdomains under `https://secure.grax.io` that you can use with no configuration; see the [Networking Requirements](/infrastructure/requirements/network-requirements) for full details.

You can also bring any domain that you own/manage. Salesforce - as well as your end users - communicates with the GRAX service with this domain (and VPN if applicable).

### Compute

To provide the processing power for your GRAX service, we recommend major cloud providers like AWS or Azure. Only a single GRAX Application may be running at any given time. Violation of this constraint may cause data and service failures. The instance may be ephemeral and doesn't contain meaningful state information. The instance may be containerized. For high availability, we recommend multi-Availability-Zone (or non-AWS equivalent) deployments and auto-replacement policies.

**GRAX isn't compatible with "bursting" instances** such as AWS's `t3` or Azure's `B` series; Resource usage by the GRAX Application is continuous. Automatic hibernation of instances when CPU usage is high directly counteracts the ability of GRAX to operate at times when your org most needs a backup.

Minimum technical specifications:

* x86\_64 Linux distribution
* 4 vCPUs
* 16 GB RAM
* 500 GB reserved disk cache (see below)
* 5+ Gbps network connection

### **Cache Space**

GRAX caches data on disk to prevent excessive network traffic and improve performance. This cache is located under `/tmp` by default on Linux systems. It must be backed by a persistent storage medium and may not use memory filesystems like `tmpfs`. To isolate the GRAX cache for ease of persistence, replacement, and maintenance, it's recommended to use a separate disk mounted at `/tmp`.

If disk configurations dictate a path other than `/tmp` be used, the `TMPDIR` environment variable can be used to point to a new path for the cache. This setting can be provided via the GRAX `.env` file.

The disk holding the GRAX cache must be an SSD (no HDDs) and must meet or exceed published performance targets of AWS's gp2 EBS volumes.

It isn't recommended to persist the GRAX cache between instance replacements.

#### **AWS Compute Recommendations**

* Minimum m7a.xlarge instance type running an Amazon Linux 2 AMI
* Minimum of gp2 EBS volume for cache

#### **Azure Compute Recommendations**

* Minimum Standard D4s v3 (4 vcpus, 16 GiB memory) instance type running RedHat 8
* Minimum Premium SSD with Read/Write Host Caching enabled for cache

#### **GCP Compute Recommendations**

* Minimum n2-standard-4 instance type running RedHat 8
* Minimum of SSD Persistent Disk for cache

### PostgreSQL

For longterm metadata and search index storage, GRAX uses a PostgreSQL relational database. This database only needs to be accessed by the instance and should not be publicly accessible. This database isn't ephemeral and data loss or availability issues halt/crash the GRAX Application. Authentication with the database happens via username/password credentials provided in the connection string. For high availability, we recommend multi-Availability-Zone (or non-AWS equivalent) deployments. The PostgreSQL major version must be at least `14.0`. We recommend you snapshot/backup the database daily with a retention of more than a month.

Please note that GRAX does not use SSL with Certificate Verification on Postgres databases; no action is needed regarding Root Certificates or Certificate Authorities as this will not impact the application.

**GRAX isn't compatible with "bursting" instances** such as AWS's `t3` or Azure's `B` series; Resource usage by the GRAX Application is continuous. Automatic hibernation of instances when CPU usage is high directly counteracts the ability of GRAX to operate at times when your org most needs a backup.

Minimum technical specifications:

* 2 vCPUs
* 4 GB RAM
* 75 GB persistent disk storage
* PostgreSQL v14+

Extensions:

* `uuid-ossp` (v1.1+)
* `pg_stat_statements`

Permissions:

The PostgreSQL credentials used in the final setup of your GRAX Application must have total/complete permissions to the database and all data within it. GRAX uses many database primitives to optimize performance and provide reliable service, thus access may be higher than a traditional app.

#### **AWS DB Recommendations**

* RDS Aurora PostgreSQL v13+ with minimum instance type db.r8g.xlarge
  * Graviton instances (`g`) offer up to 40% savings over comparable Intel based instances on AWS

#### **Azure DB Recommendations**

* Azure Database for PostgreSQL [Flexible Server](https://learn.microsoft.com/en-us/azure/postgresql/flexible-server/) v14+
  * Compute Gen 5
  * Minimum 4 vCPUs, 20 GiB Memory
  * 75 GB to start
  * `uuid-ossp` installed/enabled ([Documentation](https://docs.microsoft.com/en-us/azure/postgresql/single-server/concepts-extensions))
  * `pg_stat_statements` installed/enabled

#### **GCP DB Recommendations**

* Cloud SQL for PostgreSQL v14+
  * Minimum db-n1-highmem-4 instance type
  * 75 GB to start
  * `uuid-ossp` installed/enabled ([Documentation](https://cloud.google.com/sql/docs/postgres/extensions))
  * `pg_stat_statements` installed/enabled

### Storage Bucket

For longterm Salesforce data storage, GRAX supports AWS S3 and the Azure and GCP equivalents. GRAX doesn't support S3 Versioning, Object Lock, or Glacier (nor any equivalent features in other providers). This bucket only needs to be accessed by the instance and should not be publicly accessible. The GRAX service, in maintenance of our proprietary data format, creates and deletes objects from the selected bucket over the lifetime of the app. No data-containing objects are updated in place.

The total amount of data stored in your bucket depends on many factors that produce an unpredictable final size. Thus, we can only suggest that up to 5TB of total storage volume be available/planned in these buckets for the average customer.

Permissions:

The bucket credentials used in the final setup of your GRAX Application must have access to delete, get, update, and create all contents of the bucket. If you choose to use any encryption-at-rest mechanism (AWS KMS), you must also grant permission to use the keys in question and perform encryption operations on all objects in the bucket.

## What You May Want to Bring

In addition to the above, customers also like to use autoscaling, load balancing, and traffic filtering services for security and reliability. For high-availability and quality-of-service, we recommend an ALB positioned in front of the instance for ingress traffic. For handling of TLS encryption/certs with custom domains, see [here](/infrastructure/requirements/url-registration-for-grax#tls-ssl-certificates). We recommend the use of an autoscaling group with a size of `1` for the sake of auto-replacement and recovery. Additionally, most enterprise cloud teams use ingress and egress filtering (for example a GRAX Application firewall and/or VPC gateway) for all resources. You can find more details about the minimum requirements for networking [here](/infrastructure/requirements/network-requirements).

{% hint style="warning" %}
Applications developed outside of our specified technical standards cannot be guaranteed to perform as expected within our platform environment. Non-conformance to these specifications may result in:

* Unpredictable application behavior
* Performance degradation
* technical support challenges
  {% endhint %}


# Network Requirements

At a high level, the following are the rules for GRAX network access:

1. GRAX Application talks to Salesforce
2. GRAX Application talks to `hq.grax.com`
3. GRAX Application talks to Database
4. GRAX Application talks to Storage
5. End users talk to GRAX Application's APIs
6. *(Optional)* Salesforce talks to GRAX Application
7. `hq.grax.com` talks to Salesforce

## Communication Details

Best practices suggest exposing your GRAX Application to public traffic via an Application Load Balancer of some form with additional filtering for security. However, GRAX doesn't support API gateways that modify payloads, terminate or modify authentication, enforce third-party schemas/protocols, or filter requests based on path, payload, or parameters. GRAX doesn't guarantee alignment with any published API standard, nor promise stability of the API interface for external use at this time.

![GRAX Simplified Network Diagram](/files/6ZHBmjlcLQSESI0868ku)

## Egress Network Connections

The following are descriptions of the rules related to traffic that flows *outward from* the compute resource running your GRAX Application.

### GRAX → Salesforce

To query, update, or insert information in Salesforce, GRAX uses the public Salesforce REST and Composite APIs (and never uses the Salesforce Bulk API). Allow, at a minimum, at least one static IP for your GRAX Application to communicate out to Salesforce.

This may include allowing [SFDC Login Access from this IP](https://developer.salesforce.com/docs/atlas.en-us.securityImplGuide.meta/securityImplGuide/users_profiles_epui_login_ip_ranges_edit.htm), as well as allowing the traffic to leave the VPC or other infrastructure network.

### GRAX → HQ

For software updates, telemetry, and license monitoring, GRAX communicates with GRAX HQ. Allow the GRAX Application to access `hq.grax.com` over HTTPS on port 443. *A static IP for this communication isn't currently available.* For more information on this communication, see [here](/security/telemetry).

### GRAX → Database

For metadata storage, search indexing, and storage optimizations, GRAX uses Postgres. Allow the GRAX Application to access your configured Postgres database.

### GRAX → Storage

For longterm storage, GRAX uses blob storage platforms. Allow the GRAX Application to access your chosen blob storage bucket/platform.

## Ingress Network Connections

The following are descriptions of the rules related to traffic that flows *towards* the compute resource running your GRAX Application.

### End Users → GRAX

End users of GRAX access the GRAX Application via a web browser. This traffic originates from their local IPs unless using a VPN or proxy. To allow your users to use GRAX, allow their IPs to hit the public endpoint for your GRAX Application. If all of your users share a network segment (VPN, corporate network, etc.), allowing that network segment access may be sufficient.

### *(Optional)* Salesforce → GRAX

Lightning Web Components and Embedded Pages are all driven by Salesforce-to-GRAX traffic. Salesforce publishes their global IP ranges. Allow, at a minimum, the [IP ranges for your Salesforce instance region](https://help.salesforce.com/s/articleView?id=000321501\&type=1) to access the GRAX Application API.

**NOTE:** this traffic is optional based on feature usage. If your use case for GRAX doesn't necessitate using LWC or iFrames, Salesforce won't make requests to your GRAX Application.

## Independent Network Connections

The following are descriptions of the rules related to traffic that flows entirely *independently* from the compute resource running your GRAX Application, but which may impact its operation.

### GRAX HQ → Salesforce

GRAX HQ's static egress IPs appear in the Integration User's login history after connecting the app to Salesforce due to the nature of the GRAX OAuth process. Please add 3.232.229.75 to your whitelist/allowlist addresses on the Integration User's profile to allow the GRAX Application to connect to your org. In addition, you need to add the static IP addresses for each of your specific environments to ensure there are no IP restrictions.


# URL Registration for GRAX

The GRAX Application must be reachable by end users and Salesforce to provide backup, archive, and restore capabilities. To achieve access without a dependency on resources that may change or be replaced during the lifetime of the app, a registered domain name is utilized. We'll refer to this as the "Application URL"/"URL" below. As GRAX can be installed in many ways, the manner by which this URL is managed varies by environment.

## GRAX Legacy Heroku Apps

For older GRAX environments that run on Heroku, URLs are decided and managed by Heroku. These URLs include `herokuapp` in the path. Secure custom URLs may be used on a case-by-case basis via the Heroku management interface. Please contact [GRAX Support](/support/get-support) for assistance if interested.

## GRAX Hosted Apps

For hosted GRAX applications, GRAX creates URLs via a standard template and handles registering, renewing, and/or destroying it if no longer needed. URLs are registered as subdomains under a GRAX-owned second-level domain. Your URL is provided by a GRAX team member once provisioning is complete and the app is ready for use.

## GRAX Template Apps

Application URLs for apps both running in AWS and based on GRAX templates must be registered within Route53 and related to a hosted zone. Registering a domain manually in AWS automatically creates a related hosted zone. Registering a new domain within AWS is the recommended path for simplicity, but means that any potential corporate domain registrations won't be used. Check with your network management/IT teams prior to making this decision. If you are interested in utilizing an already-registered URL *and* a GRAX template, you need to delegate DNS for the new subdomain into Route53 from your registrar.

* Guidance on domain registration in AWS can be found [here](https://docs.aws.amazon.com/Route53/latest/DeveloperGuide/domain-register.html).
* Guidance on DNS delegation in Route53 can be found [here](https://docs.aws.amazon.com/Route53/latest/DeveloperGuide/CreatingNewSubdomain.html).

## Self-Managed GRAX Apps

Self-managed applications built without utilizing a GRAX template may achieve usage of URLs in any reasonable fashion. Equivalent capabilities to Route53 exist in nearly every public cloud. Domains may be registered and handled with your registrar of choice and delegated as required.

## TLS/SSL Certificates

The GRAX backend supports TLS encryption by default using a self-signed certificate. This ensures all traffic is encrypted no matter the source (for example from a load balancer or public internet). Optionally, users may want to provide their own certificates for a custom domain. In that case, GRAX supports the following two environment variables:

```bash
TLS_CERT_FILE
TLS_KEY_FILE
```

These environment variables tell GRAX where the custom certificate and key are located. Standard GRAX installs include a `/home/grax/.env` file where these variables can be added. For example:

```bash
# .env file containing full paths to the files
TLS_CERT_FILE=/home/grax/certs/grax-example.com.cer
TLS_KEY_FILE=/home/grax/certs/grax-example.com.key
```

#### Generate TLS/SSL Certificate

```bash
openssl req -x509 -sha256 -nodes -newkey rsa:4096 -keyout /home/grax/certs/grax-example.com.key -out /home/grax/certs/grax-example.com.cer
```

#### TLS/SSL Certificate File and Password Management

Installing TLS certificate files and supplying a key password (if any) is supported on self-managed GRAX, but is a customization you are responsible for in your infrastructure provisioning or OS service management configuration.

The password can be provided to your GRAX Application via a command during setup. It's then encrypted and stored in the GRAX database as other secrets.

```bash
# Update 'graxctl'
./graxctl update
# The 'graxctl' command is located in the GRAX installation directory, usually under /home/grax
# NOTE: Make sure to change 'passphrase1' to the actual passphrase.
./graxctl secrets -tls -cert 'cert1.pem' -key 'key1.pem' -pass 'passphrase1'
```

If the certificate isn't encrypted (no passphrase), use `-pass ''`.

```bash
graxctl secrets -tls -cert 'cert1.pem' -key 'key1.pem' -pass ''
```

After submitting the above command, you can restart GRAX to make it start using the provided password to decrypt the key file.

```bash
systemctl restart grax.service
```

#### TLS configuration precedence

GRAX looks first for TLS configuration in the secrets store. Then, if not found, on the environment file, under the `TLS_CERT_FILE` and `TLS_KEY_FILE` vars

TLS encrypted certificates (using a passphrase) can only be set using the secrets store.

## Support

If you require assistance or have any remaining questions after reviewing the above, contact [GRAX Support](/support/get-support)) with any available details.


# Architecture

While the GRAX Application interface is the main interface to backing up, protecting, and retaining your data, it's all powered by a single-tenant backend service that depends on an array of infrastructure components to perform successfully.

For a recap of GRAX features, business cases, or deployment options, see our product documentation.

## High-Level Components

The basic architecture of GRAX is:

1. Compute
2. Persistent Blob Storage
3. Persistent Indexed Storage
4. External Connectivity
5. Network Security Management

![GRAX Simplified Architecture](/files/JsnGs6qZvrbiGhvp5bGH)

The specific implementations of these simplistic labels can vary in both substance and complexity depending on deployment path chosen, platform of choice, and restrictions/regulations in place on all involved parties.

The guides in this section help explain the options you have in deploying GRAX, as well as enable your team to design, implement, and support the infrastructure yourself if so required.

## High-Level Constraints

Operating outside the scope of these limitations causes issues with data integrity, data loss, contractual agreements, and general service availability:

* Only one GRAX Application may be running for a given license.
* Only one GRAX Application may be talking to the storage bucket and the Database.
* Egress to `hq.grax.com` must be available at all times.
* Storage bucket performance must be on par with documented S3 performance metrics.


# AWS Architecture Example

The following is an architecture example for AWS deployments. This is the architecture that the AWS Marketplace offering provisions upon deployment.

![GRAX AWS Architecture](/files/gCKLHKl9q9rNo42R5vtp)


# Azure Architecture Example

The following is an architecture example for Azure deployments. This is the architecture that the Azure Terraform module follows when deploying GRAX.

![GRAX Azure Architecture](/files/W7KErJupAyuy3a8OZxiI)


# Blob Storage

For storage of record data, metadata, and file binaries, GRAX uses industry standard blob storage technologies. This is a reliable, durable, scalable, and cost effective way to retain your Salesforce data.

{% hint style="danger" %}
**Never Directly Modify a GRAX Storage Bucket**

GRAX stores record data in a proprietary format that is neither human readable nor organized in a straightforward way. Attempts to rename, remove, or modify blobs within the storage bucket **will** **cause data loss** and GRAX availability issues. GRAX isn't responsible for partial or complete loss of your backup dataset in the event of tampering by users.

For targeted record deletion (like GDPR compliance), see our [related documentation](/protect-data/purge).
{% endhint %}

## How It Works

* Metadata, files, records, and cache data are written to the bucket as part of Backup.
* The dataset is compacted and compressed as more data is added.
* The app maintains proprietary indexes on top of the dataset for performance.
* The GRAX API, Data Lake, Search, and Restore read from the dataset on demand.

{% hint style="info" %}
The Postgres database required as part of the GRAX architecture is for application metadata and is not used for storing backed up data.
{% endhint %}

## How Much it Costs

Backed up record data will consume less blob storage than reported by Salesforce. Combined with the low price of blob storage services, storage costs for GRAX almost always total a small fraction of what Salesforce would charge to store the data.

Below are some breakdowns of real-world costs of data-at-rest in AWS S3. **These don't include storage consumed by the binary component of Attachments, ContentDocuments, or EventLogFiles.** Storage usage for those binary components can currently be assumed to be 1:1 with Salesforce and estimated with published storage rates.

The extreme outlier described here is an international support organization backing up over 40,000,000,000 record versions in the last five years.

| Description      | Storage Consumed | Monthly Cost (standard S3 data-at-rest rates) |
| ---------------- | ---------------- | --------------------------------------------- |
| Average Case     | **216 GB**       | $4.97                                         |
| High End         | **5 TB**         | $117                                          |
| Extreme Outliers | **25 TB**        | $589                                          |

{% hint style="danger" %}
**Data Transfer Fees**

The calculations here only consider data-at-rest rates. All cloud providers bill for data-transfer or data-access operations. Those are considered variable costs based on usage of GRAX features and overall processing load. Our published [AWS estimate](/infrastructure/other/operating-costs) contains estimates for "normal" GET, LIST, PUT, and DELETE requests as well as overall data-transfer expectations.
{% endhint %}

## Technologies

{% tabs %}
{% tab title="AWS S3" %}
GRAX supports S3's standard storage class. Intelligent Tiering, Glacier, Outposts, Versioning, and Replication are not supported.

### Authentication

GRAX supports the following authentication patterns for AWS S3:

* Static Access Keys
* Instance Roles
* Assume Role via Static Access Keys
* Assume Role via Instance Roles

### Authorization

Regardless of authentication pattern, the following permissions must be granted at the bucket scope (`arn:aws:s3:::example`):

* *s3:ListBucket*
* *s3:ListBucketMultipartUploads*
* *s3:ListBucketVersions*
* *s3:GetBucketVersioning*

Additionally, the following permissions must be granted for all objects within the bucket (`arn:aws:s3:::example/*`):

* *s3:GetObject*
* *s3:PutObject*
* *s3:DeleteObject*
* *s3:AbortMultipartUpload*
* *s3:ListMultipartUploadParts*

The multipart-upload and versioning permissions let GRAX measure and clean up storage waste, such as incomplete multipart uploads and non-current object versions left behind by a bucket that previously had versioning enabled. When these permissions are granted, GRAX automatically aborts multipart uploads that were initiated 7 or more days ago, mirroring the [standard AWS guidance](https://docs.aws.amazon.com/AmazonS3/latest/userguide/mpu-abort-incomplete-mpu-lifecycle-config.html) to expire incomplete multipart uploads with a lifecycle rule. GRAX only inspects this waste and aborts incomplete uploads; it does not change your bucket's versioning state or lifecycle configuration. If the permissions are absent, the cleanup is skipped and you should configure an equivalent lifecycle rule yourself.

If using KMS encryption, the following permissions must be granted on the KMS key scope:

* kms:DescribeKey
* *kms:Decrypt*
* *kms:Encrypt*
* *kms:GenerateDataKey*
* *kms:ReEncrypt\**
  {% endtab %}

{% tab title="Azure Blob / Data Lake (gen2)" %}
GRAX supports standard Azure Blob Storage and Azure Data Lake (gen2) Storage accounts, including hierarchical namespaces. Premium storage accounts and gen1 Data Lake accounts are not supported. All objects must be stored in the "Hot" tier.

### Authentication

GRAX supports the following authentication patterns for Azure Storage Accounts:

* Storage Account Access Keys
* System or User-Assigned Managed Identities
* Multi-Tenant App Registration (GRAX-hosted applications only)

#### Multi-Tenant App Registration

For GRAX-hosted applications, the customer admin consents to a GRAX-owned multi-tenant app registration, creating a service principal in their tenant that they then grant RBAC access on the Storage Account. Each GRAX-hosted application has its own app registration, so consent for one doesn't extend to any other.

No tenant secret is shared with GRAX. The app registration is bound by federated identity credential to the GRAX workload's managed identity, making it non-exportable and usable only from the issuing GRAX infrastructure. Customer consent is a one-time step.

{% hint style="info" %}
To use this authentication method, contact [GRAX Support](https://documentation.grax.com/support/get-support) with your application details so it can be enabled for your environment.
{% endhint %}

### Authorization

If using an identity-based authentication pattern (managed identity or multi-tenant app registration), the following permissions must be granted at the container scope:

* *Microsoft.Storage/storageAccounts/blobServices/containers/blobs/read*
* *Microsoft.Storage/storageAccounts/blobServices/containers/blobs/write*
* *Microsoft.Storage/storageAccounts/blobServices/containers/blobs/delete*
* *Microsoft.Storage/storageAccounts/blobServices/containers/blobs/add/action*
* *Microsoft.Storage/storageAccounts/blobServices/containers/blobs/move/action*

The "Storage Blob Data Contributor" role is sufficient, but includes permission to delete the container. Custom roles are recommended for granting minimum necessary permissions.

{% hint style="danger" %}
**Double Check the Scope**

Make sure you assign storage permissions at container level, not the storage account level. These permissions at the storage account level allow the identity to interact with all data in all containers.
{% endhint %}
{% endtab %}

{% tab title="GCP Cloud Storage" %}
GRAX supports standard tier GCP Cloud Storage accounts. `Nearline`, `Coldline`, and `Archive` tiers are unsupported.

### Authentication

GRAX supports the following authentication patterns for GCP Cloud Storage:

* Service Account Keys

### Authorization

The following permissions must be granted on the bucket scope:

* *storage.objects.create*
* *storage.objects.delete*
* *storage.objects.get*
* *storage.objects.list*
* *storage.objects.update*

The built-in "Storage Object User" role grants these permissions safely.
{% endtab %}
{% endtabs %}

## Storage Replicas

GRAX can write data to multiple storage buckets simultaneously, providing additional durability and a foundation for cross-region redundancy. Each GRAX application has one *active* storage bucket (read and written) and may have one or more *passive* replicas (written only).

How replication works:

* Every write to the active bucket is split to all passive replicas at the same time.
* Reads are served only from the active bucket.
* When a new replica is added, a background sync backfills existing data automatically. Progress is shown in the storage configuration dialog.

Each replica is configured independently and has the same connection options available as the active bucket. See [Technologies](#technologies) above.

{% hint style="warning" icon="sack-dollar" %}
Each passive replica multiplies your data-at-rest costs, since every blob is written to every configured bucket. Replicas that span regions or cloud providers also incur the cross-region or egress data-transfer fees billed by the cloud provider.

Depending on the configuration, a replica may cost significantly more to operate than the active bucket and meaningfully change the total cost of ownership for GRAX. Use replicas sparingly and only where the durability or redundancy benefit justifies the additional spend.
{% endhint %}

## How It's Connected

For help connecting your GRAX application to a blob store, see our documentation for [Connecting Storage](https://documentation.grax.com/other/settings/connecting-storage).

## Frequently Asked Questions

<details>

<summary><strong>What are the data prefixes/folders written by GRAX?</strong></summary>

With the exception of the parquet folder, these storage locations contain data stored in a proprietary format and are designed to be read/written solely by the connected GRAX Application.

<table><thead><tr><th width="112">Folder</th><th>Contents</th></tr></thead><tbody><tr><td><code>grax</code></td><td>Metadata and binary components of Salesforce Files</td></tr><tr><td><code>table</code></td><td>Primary location for object and record backups</td></tr><tr><td><code>internal</code></td><td>Data generated by the GRAX application for its own use</td></tr><tr><td><code>parquet</code></td><td>Parquet files generated by GRAX's <a href="/spaces/wHKnqFEg4DROpG3KCq3D/pages/ZGht5k0UgsGqeUoiipn3">Data Lake</a> feature</td></tr></tbody></table>

</details>

<details>

<summary><strong>Can I use Data Lake with GRAX-Hosted storage?</strong></summary>

No. For security reasons, customers must use their own storage buckets for Data Lake.

</details>

<details>

<summary><strong>How can I clean deleted data from a bucket that had versioning enabled?</strong></summary>

First, ensure that Versioning is now disabled or suspended indefinitely in the bucket. Next, use provider-specific tools to automatically remove the "non-current versions" for deleted objects from the bucket. AWS S3 supports [Lifecycle Rules](https://docs.aws.amazon.com/AmazonS3/latest/userguide/object-lifecycle-mgmt.html) that can be used to automatically remove old versions of objects, and clean up delete markers left behind. A rule needs to be created to do the following:

1. **Non-current Version Expiration** - This removes the non-current versions of objects after a specified number of days. The rule should be configured to remove non-current versions after 1 day.
2. **Remove Expired Object Delete Markers** - This removes the delete markers left behind after the non-current versions are removed.

An example of a Lifecycle Rule that will remove non-current versions and delete markers after 1 day is shown below:

{% hint style="danger" %}
These examples are not filtered. They will apply to the entire bucket. If you share your GRAX bucket with other applications or data, these rules may delete non-current versions of storage objects that are not related to GRAX. *Proceed with caution.*
{% endhint %}

**XML**

```xml
<LifecycleConfiguration>
    <Rule>
        <Expiration>
           <ExpiredObjectDeleteMarker>true</ExpiredObjectDeleteMarker>
        </Expiration>
        <NoncurrentVersionExpiration>
            <NoncurrentDays>1</NoncurrentDays>
        </NoncurrentVersionExpiration>
    </Rule>
</LifecycleConfiguration>
```

**JSON**

```json
{
    "Rules": [
        {
            "Expiration": {
                "ExpiredObjectDeleteMarker": true
            },
            "NoncurrentVersionExpiration": {
                "NoncurrentDays": 1
            }
        }
    ]
}
```

</details>


# Operating Costs

## Base Costs

GRAX-Managed minimum requirements are a VM with 4 vCPUs and 16 GB of RAM, as well as a Postgres database server with dedicated capacity. These minimum requirements support small Salesforce orgs with 20 GB of data.

On AWS a base deploy costs **$260.65 / mo** for the recommended `m8g.xlarge` EC2 instance and Aurora Postgres Serverless:

* $131.05 / mo (m8g.xlarge)
* $129.60 / mo (1.5 Aurora Capacity Units)

Note that Aurora Serverless auto scales and is billed based on consumption.

On Azure a base deploy costs **$384 / mo** for the recommended `Standard_D4s_v3` VM and an `GP_Standard_D4s_v3` Azure PostgreSQL Flexible Server:

* $138.24 / mo (Standard\_D4s\_v3)
* $246.24 / mo (GP\_Standard\_D4s\_v3)

On Heroku a base deploy costs **$700 / mo** for the recommended `Performance L` dyno and `Premium 0` Heroku Postgres:

* $500 / mo (Performance L dyno)
* $200 / mo (Premium 0 Heroku Postgres)

Note that you may also want a Heroku Private Space which adds extra base costs.

Larger Salesforce orgs may need to use a larger VM or database to process data without issues. Therefore your final costs may vary. Please work with your cloud provider or contact [GRAX Sales](mailto:sales@grax.com) for help estimating the cost for the system requirements for your org.

## Cloud Cost, Usage and Optimization

GRAX takes full advantage of the public cloud to support Salesforce orgs of any size and volume: automatic high availability, effortless vertical scaling, and consumption-based pricing.

GRAX proactively monitors the health of your data, alerts you to problems affecting backups. GRAX also provides one-click tools to vertically scale your VM or database when needed for GRAX-managed environments.

The only tradeoff is that your cloud costs may vary over time and are hard to predict.

We highly recommend deploying GRAX with the minimum requirements, starting backups, then reviewing your cost and usage after 30 and 60 days. After this time your Salesforce data will be fully protected and your average cloud costs will be fully understood.

If the cost of resources is deemed too high after this time, you can:

* work with your cloud provider to buy reservations at a discount
* work with your Salesforce admin to reduce data change volumes
* work with GRAX Support to discuss deployment and product optimizations

And of course at any time you can discontinue your use of GRAX and stop all cloud resources and costs.

## Cloud Providers

### Amazon Estimate Calculator

A pre-configured estimate of the high-level AWS resources necessary for GRAX is available [here](https://calculator.aws/#/estimate?id=3c415d7c23a5673340bdb32f854297b71900af72).

All prices set by AWS are subject to change by AWS at any time, see their [pricing documentation](https://aws.amazon.com/pricing/) for more information. GRAX isn't responsible for changes to AWS pricing.

### Azure Estimate Calculator

A pre-configured estimate of the high-level Azure resources necessary for GRAX is available [here](https://azure.com/e/30cdc58d64e1430caca8f6ee2426bd6a).

## Self-Managed

GRAX Self-Managed supports whatever cloud architecture your company requires for security and compliance reasons. The architecture and related costs are ultimately up to you; we can only offer guidance on minimizing costs.

#### Never Route Storage Publicly

Never route your storage traffic external to the VPC or cloud provider. Traffic leaving the VPC crosses the NAT Gateway and incurs much higher costs; GRAX reads many Terabytes of data as it [compacts and processes your datasets](/infrastructure/other/blob-storage#how-grax-stores-your-data) so this difference adds up. This includes traffic from an AWS EC2 instance to Azure storage, or any other similar mismatch in infrastructure providers.

#### Always Provide Cache Space

Low cache size, in both memory and disk, can lead to extremely frequent read operations from storage and thus drive up overall data transfer. In infrastructures where this incurs cost, this can become very expensive. See our [technical requirements](/infrastructure/requirements/technical-requirements) for GRAX hardware to ensure you're operating within safe limits.

## FAQ

#### *What contributes to base or static costs?*

Costs that can be determined prior to usage, like the hourly cost of an EC2 instance given a 24x7x52 uptime, are considered static. These sections of the estimate aren't expected to change, regardless of GRAX features used or data processed.

#### *What contributes to variable costs?*

Many networking and storage services in the public cloud bill entirely based on usage. When it comes to GRAX's usage of RDS, S3, and NAT Gateway services, there is no exception. The estimate above includes best-attempt estimations of usage when under a typical app load. GRAX provides no guarantees as to the accuracy, in either direction, of these estimates.

There are many factors that can affect total realized costs:

* Usage of specific GRAX features
* Total Salesforce org Size
* Turnover Rate of Salesforce Records (created + changed per hour)
* Number of Files in Salesforce (each file gets downloaded and stored)
* Disk and Memory Cache Sizes [(`/tmp` + memory sizes)](/infrastructure/requirements/technical-requirements)
* Cross-Provider Storage Connections (AWS to Azure, etc. traffic bills extra)
* Public vs. Private Traffic Routing (exiting VPC may incur NAT costs)


# Monitoring

Whether you design and deploy the infrastructure for GRAX yourself or use GRAX-provided designs/templates, installing GRAX often means running cloud infrastructure within your own environment. This infrastructure isn't accessible or manageable by the GRAX team for the sake of safety, security, and compliance. Automated monitoring policies can help ensure that issues with this infrastructure are noticed quickly and downtime of your app remains low.

{% hint style="info" %}
For more information about what's covered within the scope of GRAX support obligations, review our [support documentation](/support).
{% endhint %}

## What can be monitored?

The exact observability/monitoring tools and configurations vary based on cloud provider or environment utilized for installing GRAX, but at a high-level we want to monitor major components:

1. Load Balancer (if applicable)
2. Instance Usage
3. GRAX Service
4. Postgres Database
5. Overall Health and Replacement

Cost-based alerts for budgeting thresholds and forecasts can be configured separately from the GRAX infrastructure if required. See the documentation for your cloud provider of choice for more information. Automatic restriction of resources based on cost thresholds or budgets may cause interruption to your GRAX service.

Global services (like AWS' S3 or IAM) can be monitored at a per-service level but don't require further custom monitoring individual to your account.

## Load Balancer

If your infrastructure deployment contains a load balancer for stable connectivity, it must be reachable on a given domain name with a valid certificate and have healthy targets behind it. Thus, monitoring criteria is:

1. Application domain is registered
2. Application domain is non-expired
3. Domain certificate is non-expired
4. Domain certificate is assigned to ALB
5. Certificate is installed on instance (if applicable)
6. Certificate installed on instance is non-expired (if applicable)
7. Load Balancer is reachable from intended network segment
8. Targets are healthy (see below for health checks)

## Instance Usage

The GRAX Application workload can be varied and inconsistent based on Salesforce usage. As such, occasional heavy-load periods and periods with almost no usage are normal. We recommend the following monitoring criteria:

1. CPU usage should remain below 80% on average (4-8hr roll up)
2. RAM usage should remain below 80% on average (4-8hr roll up)
3. Temp directory total size should be at least 500GB
4. Temp directory free space should be at least 15% of total size
5. Network usage should remain below 80% on average (4-8hr roll up)

For more information about the required specifications of GRAX hardware, please review the [technical requirements document](/infrastructure/requirements/technical-requirements). If utilizing AWS, more documentation on instance and auto-scaling metrics is available [here](https://docs.aws.amazon.com/autoscaling/ec2/userguide/ec2-auto-scaling-cloudwatch-monitoring.html).

## GRAX Service

Ensuring that the GRAX Application remains running on the instance is foundational to success. it's highly recommended to [run GRAX as a service with an auto-restart configuration](/infrastructure/install-guides/install-on-linux#create-a-grax-service-configuration) so that the app boots again in case of a fatal error.

### External Health Endpoint

The GRAX service offers an endpoint for an external health check like those by [AWS ALB Target Groups](https://docs.aws.amazon.com/elasticloadbalancing/latest/application/target-group-health-checks.html). Make a request like the following to check if the app is available:

```
Port: 8000 (default)
Path: /health
Method: GET
Protocol: HTTPS (HTTP1 Only)
```

If the GRAX services is running, the GET request above returns a status of `200`. This endpoint is designed for load balancer registration and de-registration, not for instance replacement.

## Postgres Database

A valid connection to the app database is required for boot and operation of GRAX. Monitoring the GRAX database isn't unlike monitoring any other app database. Monitoring should cover the following:

1. CPU usage should remain below 80% on average (4-8hr roll up)
2. RAM usage should remain below 80% on average (4-8hr roll up)
3. Total disk usage should remain below 80% (if applicable)

More options for monitoring Postgres are available based on platform/vendor including queue depth, IOPs statistics, and network throughput. For more information on how you can monitor these metrics on AWS's RDS, check out:

* [RDS Metrics Overview](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/MonitoringOverview.html)
* [Monitoring with Cloudwatch](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/monitoring-cloudwatch.html)

For similar information pertaining to Azure Postgres, check out:

* [Azure Postgres Metrics](https://docs.microsoft.com/en-us/azure/postgresql/single-server/concepts-monitoring)

## Overall Health and Replacement

The monitoring of the major components above, in combination with other standard cloud provider or environment monitors may indicate a problem that requires action to recover from.

Traditional cloud operations best practices apply, and most problems require that an operator review metrics, logs and configuration to understand and resolve the issue.

Some perceived issues require no action but waiting. Examples of this include:

* The instance restarted and is performing automatic security updates and service configuration
* The GRAX service restarted and is performing an automatic database migration
* The Salesforce API is returning 500s indicating a service outage

Other issues require manual review and action. Examples of this include:

* The instance CPU, memory or network are at 100%+ utilization, which indicates it should be reconfigured with a larger instance
* The instance disk periodically fills up and GRAX crashes, which indicates it should be reconfigured with a disk location and size that meets minimum requirements
* GRAX is crashing connecting to the database, which indicates database configuration needs to be updated

Some issues can be fully automated. Examples of this include:

* An AWS instance status check indicates a hardware failure, which an AWS autoscaling group can periodically check and automatically replace.

In all cases GRAX is designed to be simple and resilient to problems. After any amount of downtime when it resumes normal operations it will pick up where it left off.


# Rotating Infrastructure Secrets

{% hint style="warning" %}
This guide is written with the assumption that you're comfortable with the concepts from the [Native Linux Installation Guide](/infrastructure/install-guides/install-on-linux). Examples below assume an environment that matches the examples in the linked guide; if your environment differs, some commands may not work as written.
{% endhint %}

The GRAX Application requires several secret values specified in the environment (normally sourced from `.env`). These include a valid Postgres connection string, an administrator password, and a key base for encryption of the DB-based Secrets Store used for SFDC and storage connection secrets (`SECRET_STORE_BASE`). Rotation of secrets is mostly external to the GRAX Application, with one exception.

## Rotating Database Connection String or Administrator Password

To rotate the connection string used to connect to the Postgres database cluster manually, perform the following steps:

1. Stop the GRAX services

   ```bash
   $ systemctl disable grax.service; systemctl stop grax.service;
   ```
2. Update the configuration source/file with your editor of choice:

   ```bash
   $ vim .env

   [change intended key\'s value to new value and save file]
   ```
3. Start the GRAX services

   ```bash
   $ systemctl enable grax.service; systemctl start grax.service;
   ```

If you have interest in automating this behavior, the automation needs to preserve or recreate the other necessary values for the configuration.

## Rotating SECRET\_STORE\_BASE

The SECRET\_STORE\_BASE is used to encrypt the SFDC and Storage secrets in the database. Changing this value between reboots without proper care results in these secrets being irrecoverable and the GRAX Application being unable to start properly; a manual reset of configuration information in the database is the only recovery option. If this issue occurs, please contact [GRAX Support](/support/get-support) for assistance clearing the configuration.

To properly rotate this value, perform the following steps:

1. Stop the GRAX services

   ```bash
   $ systemctl disable grax.service; systemctl stop grax.service;
   ```
2. Update the `SECRET_STORE_BASE` to the new value with your editor of choice
3. Update the `SECRET_STORE_BASE_PREV` to the previous value with your editor of choice
4. Start the GRAX services

   ```bash
   $ systemctl enable grax.service; systemctl start grax.service;
   ```

At this point, the GRAX Application reads the configuration secrets with the old key and writes them with the new key on first boot. It is not necessary to remove the `SECRET_STORE_BASE_PREV` value from the configuration file. If you desire the removal of the old value, you can do so after the GRAX Application has been started successfully for two minutes; stop the services, update the `.env`, and start the services again.


# Security and Compliance

GRAX is a purpose-built high-security data processing app designed to deliver an efficient backup, archive, and restore experience while satisfying the regulatory and compliance requirements that customers face. Security is a primary design factor in all components of the GRAX Application, including infrastructure designs.

## Fully Committed

At GRAX we know we are in the privileged position of handling our customers' most valuable asset - their data. We are committed to our customers and their reliance on GRAX to handle their data correctly and in accordance with the regulatory frameworks they need to comply with. As an organization, we are committed to operating with honesty, integrity, and compliance.

## Certifications, Audits, and Reviews

GRAX has been audited to achieve SOC 2 Type 2 compliance across the platform. Alongside our security audits, our Salesforce Managed Package has been vetted and passed a rigorous and ongoing [security review](https://developer.salesforce.com/docs/atlas.en-us.packagingGuide.meta/packagingGuide/security_review_overview.htm) by Salesforce. GRAX is deployed into public cloud ecosystems and builds upon the security and compliance posture of those underlying services. For details on our compliance audit, contact [GRAX Support](/support/get-support).

If you require the provision of a BAA to support your HIPAA compliance, contact [GRAX Support](/support/get-support).

GRAX provides customers with mechanisms for authorized users to permanently delete data related to an individual (or multiple individuals). This feature is available within all product offerings.

Salesforce customers can support their PCI compliance by using Encrypted Custom Fields as the mechanism to store sensitive payment data in their Salesforce app. The GRAX Application respects the Salesforce sharing and permissions model, so individual customers can configure the GRAX user with "View Encrypted Data" permission according to their needs. Data that is handled by GRAX is encrypted in transit using TLS 1.2 and data at rest can be encrypted according to the service provider chosen.

## Salesforce Features

GRAX fully adheres to Salesforce's field and encrypted visibility settings. If a field is hidden from a user of your Salesforce org, they are unable to view that data in GRAX in any capacity. If fields are encrypted in Salesforce, GRAX must have the related permissions to view that data before it can back it up or modify it.

## Infrastructure Providers

The GRAX Application can be run in a number of public cloud providers. GRAX uses AWS as a primary infrastructure provider, but also supports customer-managed installations in Azure and GCP. For the underlying security and compliance documentation for those platforms, please refer to the relevant provider's documentation.

## Data Protections

All data is encrypted in-flight with TLS 1.2 and encrypted at rest with each provider's standard data storage encryption (that is AWS's AES-256). GRAX Managed systems maintain compliance with CA/Browser Forum Baseline TLS requirements. GRAX does not hardcode or "pin" certificates; certificates are automatically renewed based on expiration timelines. Customers managing their own infrastructure are responsible for maintaining these standards.

## Server Protections

The GRAX Application server only processes and responds to HTTPS requests. HTTP requests are ignored/rejected.

All GRAX-managed infrastructure is protected by endpoint detection and response (EDR) agents that provide continuous intrusion monitoring and threat detection capabilities. &#x20;

## Secrets Management

GRAX uses the app database for storage of the configuration values that control connections to storage and Salesforce as well as licensing information. it's recommended that the entire database storage volume be encrypted by default; regardless, GRAX encrypts the secrets additionally before they are stored in the database. This means that even users with access to the database cannot read those values without the key utilized by the GRAX Application.

In the Salesforce Managed Package, GRAX uses a Protected Custom Setting inside Salesforce to store tokens required for authentication. This is recommended practice as part of the [Secure Coding Guidelines](https://developer.salesforce.com/docs/atlas.en-us.secure_coding_guide.meta/secure_coding_guide/secure_coding_storing_sensitive_data.htm) provided by Salesforce.

## Legacy Heroku

Previous versions of the GRAX Platform have been deployed to customers using the Heroku PaaS. Heroku provides customers a network isolated environment called a Private Space that has previously been used when provisioning GRAX for customers. If you would like the compliance and security information that is particular to this type of legacy configuration, please contact [GRAX Support](/support/get-support).

## Frequently Asked Questions

### Will Salesforce’s DigiCert Global Root G2 certificate update impact my GRAX application?

No, the DigiCert Global Root G2 certificate update will not impact GRAX applications.&#x20;

GRAX systems remain fully compliant with CA/Browser Forum Baseline TLS requirements and do not hardcode or “pin” certificates; instead, certificates are automatically renewed and rotated according to standard expiration timelines.&#x20;

For customers managing their own infrastructure, responsibility for maintaining TLS compliance and certificate updates remains with the customer. That said, while both GRAX and Salesforce recommend staying current with trusted root stores such as Mozilla’s, we have taken steps to ensure all GRAX customers - whether managed or self-managed - are prepared for this change.

### Does GRAX utilize certificate pinning or hardcoded certificates?

No.


# Authentication

## Diagram

![GRAX Authentication Methods](/files/HVLkDTMZuhjyJAbvq4d8)

## Generalities

Within GRAX supplied infrastructure, all traffic is encrypted in flight via HTTPS/SSL at TLS 1.2 or higher with a public certificate (behind the ALB we recommend self-signed certificates). All data stores are encrypted by - at a minimum - AES-256. GRAX offers a pre-built secure architecture via the AWS Marketplace but choosing to use the GRAX Software on custom architecture enables you to build your own security model. As such, any operations including the transmission of network traffic or the storage of data at rest which take place on customer-provided/operated infrastructure are the responsibility of the customer.

## GRAX Token-based Authentication

GRAX uses a standard JSON Web Token ([JWT](https://en.wikipedia.org/wiki/JSON_Web_Token)) authentication flow to secure the `Managed Package` to `Backend/Instance` traffic. This is specifically traffic that the Managed Package sends to submit data, triggers, or configuration changes to the backend.

### Token

The secret used to drive the JWT authentication is generated on app installation/deployment and stored in an encrypted state in the app database. This is then passed into the Salesforce Managed Package by one of your Salesforce administrators after installation. Randomly generated via secure means that at a length of at least 30 characters, the complexity of brute forcing such a token is considered implausible. Rotation of this token isn't supported via automated means but [GRAX Support](/support/get-support) can help provide relevant details via a support request.

This token is submitted in the `x-api-token` header as part of every API request from the managed package to the backend which contains, accesses, or controls data. Endpoints such as job summary reports (which contain only object names) aren't secured for ease of sharing/review. These paths, however, are all the concatenation of many randomized IDs and not regarded to be "guessable."

The full list of token secured endpoints isn't available for security reasons.

### Salesforce Storage

The GRAX Tokens are stored on the Salesforce side within a protected custom secret. For more information on these, see [here](https://help.salesforce.com/s/articleView?id=sf.cs_schema_settings.htm\&type=5). Modification to these values is accomplished via the GRAX Managed Package GUI.

### Verification

When the backend receives a request from the Managed Package that requires authentication, it verifies the supplied API token against the token loaded in the app configuration. This configuration loads the contents of the connected AWS Secret, sources the value from the attached Database, or reads from the local environment on each boot.

### Use Case Example

Joe Smith is an ABC Company Salesforce Administrator. He is newly responsible for configuration and maintenance of the GRAX Managed Package as well as the related data backup operations. He logs into Salesforce, chooses the GRAX app from the "app launcher," and is greeted by the GRAX "Configuration" tab. He switches to the "Schedule" tab and selects "Execute Now" on an existing backup job. This sends a request to the backend, secured via the afore-mentioned token, which is verified against the expected token value. This request adds the backup job to the internal work queue.

## GRAX SSO via Salesforce

Within the GRAX Application experience, authentication is driven by the user's Salesforce access. Via this control, your admins can completely prevent access to GRAX, hide fields, hide features, and/or grant permission to modify general app settings.

### OAuth Sessions

There are always two login types to consider with GRAX: the integration user (for backing up/archiving/restoring data) and the user that logs into the GRAX interface to run said archives, restores, or searches. The integration user must have extensive permissions and be connected to the GRAX backend via OAuth. To be a user of GRAX, your Salesforce user must be given a custom permission set, named along the lines of "GRAX - \[Name]" (that is "GRAX - Configuration Admin").

{% hint style="warning" %}
**Please note that 'Log In As' (**[**User Impersonation**](https://help.salesforce.com/s/articleView?id=sf.logging_in_as_another_user.htm\&type=5)**) does not work with OAuth**
{% endhint %}

### OAuth Flow

The OAuth flow for the GRAX Application consists of multiple steps. First, the GRAX backend calls out to `hq.grax.com` with the OAuth request. This GRAX service then proxies that request to Salesforce, relating it to a unified GRAX Connected App configuration. After generating an access token for the user session, this GRAX service discards the session token and passes the access token back to the backend. The backend then uses the received access token to generate a new session.

This multi-party flow is a requirement of GRAX licensing processes as well as ensuring GRAX works under several of the more restrictive Salesforce security options. No credentials, session tokens, or access tokens are stored within the GRAX beyond the lifetime of the specific authorization events they're related to. All related data stores are encrypted. Login attempts against the user as part of this flow originate from 3.232.229.75.

### Permissions Management

GRAX respects [field](https://help.salesforce.com/s/articleView?id=sf.admin_fls.htm\&language=en_US\&r=https%3A%2F%2Fwww.google.com%2F\&type=5) level security to protect your sensitive data within the GRAX application, as well as, its corresponding GRAX Lightning Web Components. GRAX also supports “row” (record) level security implicitly within the GRAX Lightning Web Components based on a user’s access to the Parental record the LWC resides.

For added guarantees you can prevent integration user access to specific data so that it can never be seen, read, backed up, archived, or restored by GRAX and thus avoid the whole end user access issue in the first-place. We don't recommend this, as that data cannot be protected in backups in this case. To manage this visibility, simply manage it as your normally would in Salesforce.

GRAX drives Application access permissions based off of custom permission sets which are installed alongside the managed package and can be customized by advanced users. To grant a user access to the permissions covered under a permission set, simply assign them that permission set.

### Use Case Examples

Joe Smith is an ABC Company Salesforce Administrator. He is newly responsible for restoring all Cases to their value as of last Friday. He connects to the GRAX Application URL (unique for each customer), logs in with SSO via his intended Salesforce org, and navigates to the "Restore" page. He chooses a Salesforce report as the source for Case IDs from a list populated by the backend polling the Salesforce REST API with the integration user's OAuth session token. After clicking next, the restore execution begins processing. During this time, the GRAX backend is querying the Salesforce API and GRAX storage to build a restore plan for the cases. Once Joe triggers the restore execution to run after processing is complete, the GRAX backend begins submitting REST calls to the Salesforce API with the integration user's session token to create records.

Jane Smith is an ABC Company Support Associate. She receives a customer complaint referencing a major case from 13 months ago. ABC Company's Salesforce leadership has opted to archive any cases last modified more than 9 months ago with GRAX. Jane navigates to the "Related" tab on the Account record and uses the GRAX Related Records component to see the archived case record, review the fields, and even restore that case along with related records (via linking into the GRAX Application). All data retrieval in this scenario and the potential jump into the GRAX Application are powered by Jane's OAuth session with her Salesforce org. The API calls for records originate on Jane's machine, and are verified via the OAuth process when they arrive at the GRAX Application.

## Telemetry Data

Telemetry information, app level statistics about the internal performance of the GRAX system, is sent out to `hq.grax.com` on a regular interval. This information doesn't contain any of your Salesforce data. The connection to `hq.grax.com` is write-only and secured via a combination of username and password used in the basic authentication process.

## Data Storage Authentication

### PostgreSQL

Authentication to the app database is protected via "Password" authentication, as seen [here](https://www.postgresql.org/docs/9.1/auth-methods.html). No other authentication methods to the database are currently supported. GRAX does not use SSL with Certificate Verification on Postgres databases; no action is needed regarding Root Certificates or Certificate Authorities as this will not impact the application.

### AWS S3 (or Azure/GCP alternatives)

As a general rule, the GRAX product supports the most common and accepted authentication methods for each bucket/blob storage provider. Details for each are linked below:

* [AWS S3 Access Keys Documentation](https://docs.aws.amazon.com/AmazonS3/latest/userguide/S3_Authentication2.html)
* [Azure Blob Storage Shared Key Documentation](https://docs.microsoft.com/en-us/rest/api/storageservices/authorize-with-shared-key)
* [GCP Blob Storage Private Key Documentation](https://cloud.google.com/storage/docs/authentication)


# Telemetry

GRAX monitors deployed software via egress-only log and telemetry streaming technologies. This allows the GRAX team to best ensure reliability without need for ingress connections or direct environment access, both of which have security implications. This document explains both of the methods in use today by GRAX and describes the data contained by both.

## GRAX Metrics

Metrics are quantitative expressions of app performance, health, and configuration; their numerical nature assists in detection of failures. GRAX calculates and streams metrics continuously as the app runs. Telemetry regarding system resources (CPU, RAM, Disk, etc.) is streamed continuously, but the GRAX Application submits specialized telemetry events occasionally. These include, in part:

* At time-of-boot
* At time-of-update
* Changing configuration of:
  * Backup
  * Search
  * Data Lake
  * General Settings
* Processing tasks change status (created, started, ended, failed, etc.):
  * Archives
  * Restores

## GRAX Logs

Logs are more detailed and structured than app metrics; they're traditionally used for investigating issues -- not detecting them. GRAX streams logs with an authenticated egress-only connection, making application logs available to GRAX Engineering for the sake of supportability and bug-fixing. Here are some related key details:

* GRAX logging never contains your Salesforce records or any system secrets.
* Logs use the same authenticated `hq.grax.com` connection as licensing and metrics.
* Access to these logs is tightly controlled internally at GRAX.
* Logs are retained indefinitely.
* This cannot be disabled.

Logging uses a forward-only collector and won't transmit logs from an earlier point in time.

### What do GRAX logs contain?

Logs emitted by GRAX never contain customer CRM data, PII, or secrets. These logs are intentionally designed to be useful for GRAX engineers; as such, they contain:

* Source Function Names
* Source filenames
* Function Timing Information
* API Request Methods
* API Request Paths
* CPU Performance Metrics / Profiles
* Memory Performance Metrics / Profiles
* Storage Performance Metrics / Profiles
* Function Metadata (Object Names, Batch Sizes, Record Counts, etc.)

As you can see, the data logged within the GRAX logging system is strictly related to operation and performance of the GRAX Application with no exposure of protected data at any time.

As stated above, logs from GRAX are intended for consumption by GRAX engineers. We don't publish documentation nor provide training on understanding the internals of the GRAX Application. This means that logs won't provide value to teams monitoring GRAX directly without the assistance of GRAX support.

### Who can view GRAX logs?

Your logs are only visible to the engineers who directly support and manage operation of the GRAX Application. For more information about security controls, audits, and compliance, see [here](/security).

## Network Considerations

This is required for the GRAX Application to operate. As such, egress to `hq.grax.com` is required at all times from the app. *A static IP for this communication isn't currently available.* Without this access, the app won't boot or run; this isn't configurable.

## Data Security

GRAX takes security of customer data seriously. As such, none of your Salesforce data ever leaves the app environment. A breakdown of collected data follows:

* Names of Salesforce objects (Standard and Custom) covered by backup and archive operations.
* Number of records for Salesforce objects (Standard and Custom) covered by backup and archive operations.
* GRAX backup/archive/restore configurations (schedule, start time, etc) and statuses.
* Size, performance, and internal metrics for the proprietary GRAX storage layer in your storage bucket.
* Size and performance metrics for the attached Postgres database.
* Total data size sent and received to/from Salesforce.
* Feature status (feature flags, feature access levels)
* Structured app logging (optional)

No sensitive, classified, or restricted data or PII is included in telemetry communications. The content of backed up records isn't inspected for telemetry, nor is it made available to any GRAX engineers.

All data is encrypted with HTTPS and TLS 1.2+ while in flight, and encrypted on disk when at rest. Access to the telemetry dataset is restricted within the GRAX team to only engineers whose roles require access.

## Third Party Tools

GRAX uses third party tools and services to protect, store, and analyze telemetry data. The current telemetry tool set includes:

* [Datadog](https://www.datadoghq.com/) for ingestion and consumption
* [AWS S3](https://aws.amazon.com/s3/) for archival

Telemetry archives are encrypted at rest with AES-256 encryption.

## Frequently Asked Questions

#### *Can I save GRAX Application logs?*

GRAX forwards app logs to a central GRAX service to help with automatic monitoring and customer support. GRAX retains these logs indefinitely. For more details see here [here](/security/telemetry).

However, in self-managed GRAX deployments, you are in control of the configuration of your GRAX Application servers, and can configure them to forward logs to your own external storage systems.

How to do this depends on how your server is configured to run GRAX, as well as what log storage system you use. If you are using the standard GRAX AWS templates, GRAX logs go through:

* systemd journal
* rsyslog
* `/var/log/grax.log`
* AWS CloudWatch

Consult with your cloud team and logging service provider on how to configure the server to forwarding from one of these subsystems.

#### *Can I use GRAX Application logs for auditing?*

In self-managed GRAX deployments, after you forward logs to your own logging service, you also are in control of how these are used, and can use them for auditing, monitoring and alerting.

While the format of application logs is subject to change, every API call is logged and includes:

* HTTP method, path, and status
* Remote address and user agent
* Salesforce Org ID and User ID of the caller

Here is an example log for when the user with ID `0054o000002Yz6lAAC` updated storage settings:

```json
{"keys":{"jwtAuth":"sfid_00D770000008i1kEAA_0054o000002Yz6lAAC","method":"PUT","path":"/api/v1/secrets/StorageSecret","remoteAddr":"[2600:1700:9da3:c850:3c02:8217:4d9f:2507]:52529","route":"/api/v1/secrets/:id","status":200,"userAgent":"Mozilla/5.0"}}
```


# Secure Endpoints

For GRAX-Hosted and GRAX-Managed deployments of the GRAX Application, customers can take advantage of GRAX-provided secure endpoint technology to reduce cost, improve security posture, reduce infrastructure complexity, and shorten initial deployment time.

## What is a Secure Endpoint?

GRAX utilizes a third party service, `ngrok`, to expose applications at controlled domain names. Each application generates a subdomain on `secure.grax.io` when it first starts and this subdomain is used to access the application. This subdomain is unique to the application and is secured with a globally unique set of credentials. Every time the GRAX Application launches, it establishes a connection with the `ngrok` services, creates a tunnel, and begins serving content at the associated subdomain.

## What is ngrok?

ngrok is third-party service that provides secure networking tools for internal and production use cases. Their [website](https://ngrok.com/) can be found here, and their trust site with compliance and security information can be found [here](https://trust.ngrok.com/). GRAX uses the ngrok product as a SaaS component of select provided services.

## Why does GRAX use Secure Endpoints?

#### Cost and Complexity

In a traditional cloud infrastructure stack designed to run a monolithic internet facing application, the following components are required just to get traffic in to the application securely (some data storage resources are absent from this list for simplicity):

1. Public Domain Name
2. Application Load Balancer
3. DNS entry to direct traffic to the Load Balancer
4. Web Application Firewall
5. Application Server

In GRAX-managed deployments, only the application server is necessary to serve traffic. This reduces complexity of the infrastructure and reduces the overall cost of ownership of GRAX. This also means that all GRAX-managed and hosted deployments share the same ingress pattern (not secrets), making all applications part of a consistent monitoring, security, and maintenance process regardless of Cloud Provider and installation environments.

#### Security

Environments deployed to use a secure endpoint are, at the infrastructure level, configured with zero means of external ingress to any resource. The application server is not reachable from outside the containing security group or VPC/VNET and data stores are only accessible from the application server. This means that there is a reduced risk of extraneous or accidental exposure of attack surfaces as doing so would require substantial changes to network security resources instead of a mere misconfiguration of a security group or VPC/VNET.

Additionally, since the GRAX Application never binds to a static pre-determined port in these deployments, the opportunity for a malicious service to take over that port and serve traffic from your ALB is eliminated. The GRAX Application creates, maintains, and protects the tunnel to the `ngrok` service as part of the application lifecycle, not as a static configuration within the server file system. The secrets that are used to establish the tunnel are unique to the application and are not stored locally on the server.

If customers wish to take a advantage of additional features of `ngrok` such as custom domains, integrated WAF, DDoS protection, etc., they can do so by contacting GRAX Support.

#### Deployment Time

Requiring a public domain name, DNS changes, and an ingress path infrastructure that may be run in an otherwise isolated network segment can add significant time and complexity to any deployment of GRAX. This often means that several teams need to be involved immediately in the deployment process before even the first resource gets deployed. A secure endpoint avoids the need for those resources, allowing the GRAX Application to be deployed and running in minutes instead of hours or days.

#### Portability

GRAX is an enterprise solution under constant development and improvement. This includes reliability, efficiency, performance, cost, security, and portability improvements that allow the application and service to meet the goals of a varied customer base. Architectures that reduce the dependency on cloud provider specific services and resources allow GRAX to install across competing providers (AWS, Azure, GCP), across environments of different scales (Cloud, On-Prem, Docker, or a Laptop), and across different deployment models (Managed, Hosted, Self-Managed) with minimal inconsistencies between environments.

This also means that the application environment itself is more portable since connectivity of end users is controlled by the application. Failing over to an alternative geographic zone or region does require changing the ingress path or modifying DNS rules on the fly. Simply boot the application with data stores that contain the same information in a new region, account, zone, or even cloud provider, and focus on the rest of your business.

## How does the GRAX Secure Endpoint System Work?

GRAX-managed and GRAX-hosted applications are designated to use a secure endpoint upon creation within [GRAX Platform](https://platform.grax.com). When the infrastructure deployment is completed, the application checks in with `hq.grax.com` for purposes of licensing, telemetry, and secure endpoint management. The application then establishes a connection with the `ngrok` service based on data retrieved from `hq.grax.com`. This interaction with `ngrok` happens entirely within the GRAX Application via the `ngrok` [Agent SDK for Go](https://pkg.go.dev/golang.ngrok.com/ngrok). When the GRAX Application is offline, a default error page is displayed by `ngrok` automatically whenever someone tries to access the application subdomain.

## Questions?

If you have any remaining questions about GRAX secure endpoints, please reach out to GRAX Support for more information.


# Security Testing

GRAX periodically conducts its own penetration tests, undergoes external penetration tests, and completes other security audits. These results are available to our customers via the [GRAX Trust Center](https://trust.grax.com/resources). To view the results, click `Request Access`, and you'll receive a notification once access has been granted.

If you are interested in performing your own penetration tests of GRAX, please contact [GRAX Support](/support/get-support) with details of your testing processes and schedule to get approval for any penetration testing.

Our cloud service providers also publish their own security reports and penetration testing guidance:

* [ngrok Security Portal](https://trust.ngrok.com/)
* [AWS Penetration Testing](https://aws.amazon.com/security/penetration-testing/)
* [Azure Penetration Testing](https://learn.microsoft.com/en-us/azure/security/fundamentals/pen-testing)


# GovCloud Deployment

## What's GovCloud?

[AWS GovCloud (US)](https://aws.amazon.com/govcloud-us/?whats-new-ess.sort-by=item.additionalFields.postDateTime\&whats-new-ess.sort-order=desc) Region is an isolated Amazon Web Services environment used by US government agencies at the federal, state, and local levels, along with contractors, researchers, educational institutions, and other US customers.

## GRAX and GovCloud

* GRAX has received the [Government Cloud badge from Salesforce](https://appexchange.salesforce.com/listingDetail?listingId=a0N3A00000FMtthUAD\&tab=e)
* GRAX is compatible with [AWS GovCloud](https://aws.amazon.com/govcloud-us/?whats-new-ess.sort-by=item.additionalFields.postDateTime\&whats-new-ess.sort-order=desc)

You deploy GRAX into your GovCloud cloud PaaS such as AWS, Google Cloud, Azure, and others. In fact, many agencies and customers deploy and manage their own GRAX deployment in their cloud with the majority of our customers using AWS, Google Cloud, Azure, or a hybrid or multi-cloud environment. Other customers find that they can install and run a self-managed deployment of GRAX by placing it in a GovCloud-authorized data center and using a GovCloud-authorized Cloud Service Provider.

#### Key points about running GRAX within GovCloud certified environment

* GRAX doesn't have access to the data or infrastructure
* Customer data is 100% owned by the customer within their GovCloud certified infrastructure
* Customers can use private routing between Salesforce and AWS
* Customers can use private routing between their infrastructure to GovCloud certified PaaS environment
* Customers data is 100% owned and stored within their GovCloud PaaS environment

GRAX architecture and deployment model has received the [Government Cloud badge from Salesforce](https://appexchange.salesforce.com/listingDetail?listingId=a0N3A00000FMtthUAD\&tab=e)

![GRAX's Salesforce AppExchange Listing](/files/KVS2otk7qKRmwzgGPkOO)

To learn more about GRAX and how we support public sector agencies, departments, and organizations, please contact us. For more information on AWS's compliance with federal and other standards, see [AWS's compliance page](https://aws.amazon.com/compliance/).


# FedRamp Deployment

## What's FedRamp?

The Federal Risk and Authorization Management Program (FedRAMP) is a government-wide program that provides a standardized approach to security assessment, authorization, and continuous monitoring for cloud products and services. [See the GSA definition](https://www.gsa.gov/technology/government-it-initiatives/fedramp).

Specifically, FedRAMP is focused on cloud products and services, evaluating and certifying cloud PaaS, IaaS, and SaaS offerings. Details about the [FedRAMP program](https://www.fedramp.gov/) highlight the process and status of how cloud services are assessed and certified in the FedRAMP marketplace.

## GRAX and FedRAMP

You deploy GRAX into your FedRAMP cloud PaaS such as AWS, Google Cloud, Azure, and others. In fact, many agencies and customers deploy and manage their own GRAX Application in their cloud with the majority of our government customers using an on-premise deployment of our software product in their cloud environment (like AWS, Google Cloud, or Azure) or in a hybrid or multi-cloud environment. Other customers find that they can install and run the GRAX Application by placing it in a FedRAMP-authorized data center and using a FedRAMP-authorized Cloud Service Provider.

To learn more about GRAX and how we support public sector agencies, departments, and organizations, please contact us.

For more information on AWS's compliance with federal and other standards, see [AWS's compliance page](https://aws.amazon.com/compliance/).


# Release Notes

GRAX publishes two sets of release notes. One set is related to changes within the GRAX Managed Package, while the other is related to feature changes in the GRAX backend application. See the table below for more information about available release notes.

### GRAX Application Release Notes

{% hint style="info" %}
The GRAX Application is not available in versioned releases. All GRAX applications automatically update themselves on a regular schedule and only the latest GRAX release is available from our download APIs at any given time. These release notes are based on date and are intended to align with feature additions or changes.
{% endhint %}

| Release        | Link                                                         |
| -------------- | ------------------------------------------------------------ |
| May 2026       | [Notes](/notices/release-notes/may-2026-release-notes)       |
| April 2026     | [Notes](/notices/release-notes/april-2026-release-notes)     |
| March 2026     | [Notes](/notices/release-notes/march-2026-release-notes)     |
| February 2026  | [Notes](/notices/release-notes/february-2026-release-notes)  |
| January 2026   | [Notes](/notices/release-notes/january-2026-release-notes)   |
| December 2025  | [Notes](/notices/release-notes/december-2025-release-notes)  |
| November 2025  | [Notes](/notices/release-notes/november-2025-release-notes)  |
| October 2025   | [Notes](/notices/release-notes/october-2025-release-notes)   |
| September 2025 | [Notes](/notices/release-notes/september-2025-release-notes) |
| August 2025    | [Notes](/notices/release-notes/august-2025-release-notes)    |
| July 2025      | [Notes](/notices/release-notes/july-2025-release-notes)      |
| June 2025      | [Notes](/notices/release-notes/june-2025-release-notes)      |
| May 2025       | [Notes](/notices/release-notes/may-2025-release-notes)       |
| April 2025     | [Notes](broken://pages/pOUi5qY8X4DY64NZfRIm)                 |
| March 2025     | [Notes](broken://pages/p04z423qJNbZJuw1jGzV)                 |
| February 2025  | [Notes](broken://pages/rQ4dTg8PCBcYkRbC6Hmb)                 |
| January 2025   | [Notes](broken://pages/2IUBK0e168vKAtn2pWPY)                 |

### GRAX Managed Package Release Notes

{% hint style="warning" %}
Release notes for Managed Package versions prior to 3.97 have been removed to ensure the relevance of the following list.
{% endhint %}

| Version | Date          | Link                                               |
| ------- | ------------- | -------------------------------------------------- |
| 4.00    | June 2023     | [Notes](/notices/release-notes/4.00-release-notes) |
| 3.99    | December 2022 | [Notes](/notices/release-notes/3.99-release-notes) |
| 3.98    | October 2022  | [Notes](/notices/release-notes/3.98-release-notes) |
| 3.97    | July 2022     | [Notes](/notices/release-notes/3.97-release-notes) |


# June 2026 Release Notes

## GRAX Changelog - June 2026

***

### Search

**More reliable search downloads, especially for large result sets** - When you run a search in GRAX, you can now export the results as a downloadable file without copying records by hand. GRAX runs the export as a background job and retries automatically if Salesforce is slow to respond. Only the user who started the download can view or retrieve the result, keeping search exports private by default.

***

### Backup & Restore

**FlowOrchestrationLog is now backed up automatically** - The FlowOrchestrationLog object requires explicit Salesforce permissions that many orgs do not have set by default. GRAX now detects when these permissions are missing and applies them automatically if the auto fix permission setting is enabled. This is now active for all Salesforce organizations.

**Rich text field backup handles more image and attachment error states** - Rich text fields can contain both embedded images and anchor links that point to external files. GRAX now correctly tells these apart, so an anchor link to a missing or inaccessible file no longer stalls backup of the surrounding record.

**File attachment links are now included in backup for all organizations** - Salesforce connects records to their attached files through document link records, GRAX now backs up those links alongside the records themselves. This ensures file attachments stay associated with the correct records when browsing or restoring data.&#x20;

**Apex CPU limit errors no longer stop backup** - Orgs with complex Apex triggers or large data volumes sometimes receive a CPU time limit error from Salesforce during archive jobs. When this happens, GRAX now breaks the affected batch into smaller chunks and retries each piece separately, rather than stopping the whole job. Records that would previously have been missed are now captured.

***

### UI

**Turn off navigation links in the GRAX Lightning Web Component** - The GRAX Child Record Viewer Lightning Web Component now supports a no-links mode for Salesforce page layout embeds. When this mode is active, the record title, email view button, and record ID display as plain text instead of links, so users can view the data without clicking through to other pages. Admins can apply this on any layout where navigation away from the record is not appropriate.

**Secondary storage sync now shows a record count** - Passive storage sync - used when GRAX mirrors backup data to a second storage location - now shows a count of records waiting to be copied. Admins managing a two-storage setup can see at a glance how many records are still queued, making it easier to confirm that secondary storage is staying current.


# May 2026 Release Notes

## GRAX Product Updates

### May 2026

May brought meaningful improvements across search, backup reliability, and Salesforce connectivity. The standout addition is the ability to download search results directly from GRAX, with email notification when large exports are ready. Connection reliability for Salesforce got stronger, archive workflows became more self-managing, and several quality-of-life improvements landed across the interface.

***

### Backup & Restore

#### Salesforce Connections Now Handle Refresh Token Rotation Automatically

**What Changed:** GRAX's Salesforce OAuth connection management now automatically handles refresh token rotation, saving updated tokens when they change and continuing without interruption.

**Why This Matters:** If your Salesforce organization uses a connected app with refresh token rotation enabled, your GRAX connection now stays active and renews itself without requiring manual reconnection. Backup jobs continue reliably even when tokens cycle on schedule.

***

#### Rich Text Field Backfill Is Now More Resilient

**What Changed:** The Rich Text Field (RTF) backfill process now handles records with missing or broken inline images gracefully, continuing through to completion regardless of image availability.

**Why This Matters:** RTF backfill jobs now complete reliably across your full data set. If you have a stalled RTF backfill, it is worth restarting it so it can run through to completion.

***

### Archive

#### Archive Recurrences Now Auto-Disable When Salesforce Marks Objects as Non-Deletable

**What Changed:** When an archive recurrence targets a Salesforce object that Salesforce marks as non-deletable, GRAX now automatically disables the recurrence and sends a notification, matching the behavior already in place for other unsupported configurations.

**Why This Matters:** Previously, these recurrences would continue running and failing without a clear signal. Now you receive a notification when a recurrence is stopped, so you can review your archive configuration and make adjustments with full visibility into what changed and why.

***

### Search

#### Search Results Can Now Be Downloaded, with Email Notification for Large Exports

**What Changed:** Search results can now be exported in the background from the GRAX interface. For exports that take more than one minute to prepare, GRAX sends an email notification when the download is ready, including a direct link to retrieve the file.

**Why This Matters:** Large search exports no longer require keeping a browser window open and waiting. Start a download, continue your work, and retrieve the results when you get the notification. This makes it practical to export large data sets on demand without disrupting your workflow.

***

#### Search Results Load More Smoothly

**What Changed:** The search results table now shows a loading indicator while results are being fetched, rather than displaying a partially rendered or transitioning state between queries.

**Why This Matters:** The search experience is now more consistent and easier to read. You will always see a clear loading state while your query runs, rather than a blank or flickering table, so it is easy to tell when results are incoming versus complete.

***

### User Interface

#### Deprecated Salesforce Authentication Now Shown as a Prominent Banner

**What Changed:** Customers still using Username and Password authentication for their Salesforce connection now see a banner-level notice that this method has been deprecated, replacing the smaller inline warning that was shown previously.

**Why This Matters:** If your GRAX instance is connected to Salesforce using Username and Password credentials, this banner is a direct call to action. Migrating to OAuth-based authentication now will prevent disruption when the deprecated method is fully retired. Contact your GRAX customer success team if you need guidance on making this change.

***

### How to Get the Most from These Updates

* **Try search downloads for your next large export.** If you regularly pull large data sets from Search, start a download and let the email notification do the waiting for you. You will get a direct link as soon as the file is ready.
* **Check for stalled RTF backfill jobs.** With the image-handling improvement in place, any RTF backfill that previously stopped on a broken image should now be able to complete. Restart any that are in a stopped state.
* **Review archive recurrence notifications.** If any of your archive recurrences were auto-disabled this month, check the notification to understand which objects were affected and whether your configuration needs to be updated.
* **Respond to the deprecated auth banner if you see it.** Customers still on Username and Password authentication for Salesforce should plan a migration to OAuth now. Your customer success team can walk you through the process.

***

### Questions or Feedback?

Reach out to your GRAX customer success team or contact support at <support@grax.com>.

***

*May 2026*


# April 2026 Release Notes

## GRAX Release Notes — April 2026

***

### Storage

**Active/Passive Storage.** You can now configure a passive storage location alongside your primary storage. GRAX syncs your data from active to passive in the background, and the storage settings page shows sync progress as a percentage. AWS cross-region passive storage is supported. This is useful for disaster recovery, multi-region redundancy, and compliance requirements that need a second copy of your data in a separate location.

**Azure Storage via OAuth app registration.** GRAX can now connect to Azure Blob Storage using a multi-tenant OAuth app registration instead of a storage account key. Azure authentication method options are available in storage settings. This gives Azure customers more secure and manageable storage connections without sharing long-lived credentials.

**Improved S3-compatible storage support.** GRAX now handles checksum and authentication requirements correctly for S3-compatible storage providers beyond AWS — including Dell ECS and other custom endpoints. Customers running GRAX against non-AWS object storage will see more reliable connections.

***

### Search

**Search is faster and more accurate.** The search backend has been upgraded to V2. Reference-field searches now pass improved object context for better index usage. Filtering by Salesforce record ID now works correctly when AND is the default operator. 18-character Salesforce IDs are normalized for case-correct matching. The old V1 search endpoint has been retired.

**More precise search export field selection.** When you download search results, GRAX now exports exactly the fields you have selected at the time of download. Previously, the field list could reflect an earlier selection if you changed it before downloading. Search exports now represent your current field configuration.

***

### Restore

**Restore now includes embedded images in rich text fields.** Records with images embedded in rich text fields — case descriptions, knowledge articles, email bodies — now carry those images through restore and sandbox seeding. Previously, inline images were silently excluded from the restored output.

**Formula fields stay current after data operations.** Formula field refresh now runs across all objects following restore and other data operations, not just a subset. Formula values should reflect current underlying data more consistently across your org.

***

### Govern

**New Governance preview is available.** This uses existing salesforce settings for Sheild, Data Sensitivity, and Compliance Groups to create a new datalake that protects this data while making non-sensitve data available to more uses. It now shows a list of fields that are protected, along with the reason each field is protected. This is in preview by request.

***

### Backup

**Sandbox backup consistency improvements.** Sandbox environments now use snapshot pinning for backup and search, and sandbox backfill jobs run independently of production. This means sandbox and production backup schedules no longer interfere with each other, and the data visible in a sandbox reflects a consistent point in time.

***

### Security

**Audit activity logging.** GRAX now can log all audit events internally, including the source IP address of the request. This supports security review, compliance reporting, and investigation workflows for customers who need visibility into who accessed or changed what.

***

### Coming Soon

**Salesforce username/password login retires June 1, 2026.** GRAX is retiring support for connecting to Salesforce via username, password, and token credentials on June 1. If your GRAX instance still uses this connection method, you need to reconnect using OAuth before that date. You should have received an email with instructions. Contact support if you need help reconnecting.


# March 2026 Release Notes

## GRAX Product Updates

### March 2026

March was a strong month for data fidelity and transparency. We shipped meaningful improvements to how GRAX captures and displays rich content, gave you more control over archive operations with related records, and launched an audit log so you can see exactly what's happening in your org. We also continued investing in sandbox seeding reliability and data lake flexibility.

***

### Backup & Restore

#### Images in Rich Text Fields Are Now Backed Up and Displayed

**What Changed:** GRAX now backs up images embedded in Salesforce Rich Text Fields. This includes inline images referenced from records  and displays those images correctly when you view records in the GRAX Console.

**Why This Matters:** Previously, rich text content in GRAX could appear with broken or missing images. Now what you see in GRAX matches what's in Salesforce. This applies automatically to your existing and future backups with no configuration required.

***

### Archive

#### Archive Now Lets You Include Related Child Records

**What Changed:** When setting up an archive job, you can now choose to include all related lookup child records automatically, or select specific child objects manually from a relationship tree.

**Why This Matters:** Archiving a parent record without its children could leave orphaned records in Salesforce or result in incomplete data sets. This new control lets you archive related data cleanly in a single operation, reducing follow-up cleanup and improving data integrity across your org.

***

### Search

#### Content Documents with Backed-Up Assets Are Related to Parents

**What Changed:** GRAX search identifies Content Documents that have associated backed-up assets as non-orphaned records.

**Why This Matters:** These documents were previously appearing as "orphans" in search results, which could be misleading and affect how you managed your archived data. Search results now reflect the actual state of your data more accurately.

***

### User Interface

#### Recurring Activity List Now Loads All Pages

**What Changed:** The recurring activities list now supports infinite scroll, allowing you to page through all of your recurring backup or archive jobs without hitting a cutoff.

**Why This Matters:** If you manage a large number of recurring jobs, you were previously limited to viewing only the first page. You can now scroll through the full list without any workarounds.

***

#### Clearer Behavior When GRAX Is Disconnected from Salesforce

**What Changed:** When GRAX is in a disconnected state, backup-related pages are now appropriately limited, and object search in the header is disabled to reflect that live data isn't accessible.

**Why This Matters:** Previously, disconnected mode could leave some pages in an ambiguous or partially broken state. The UI now clearly reflects what's available. This reducing confusion about what's happening and why certain actions aren't available.

***

### Sandbox Seeding

#### Seed Jobs Now Include Optional Parent Records

**What Changed:** When GRAX builds a seed graph, it now includes optional (non-required) parent relationships. For example, a Product linked to an Asset, so those parent records are created or updated as needed in the target org.

**Why This Matters:** Seeds that involved optional parent references could produce incomplete data sets in the target sandbox, requiring manual follow-up. Seeds are now more complete by default.

***

#### Sandbox Seeding Batch Limits Now Apply to Search-Based Jobs

**What Changed:** When creating a seed job from a saved search, you can now set a record limit directly in the seed configuration. This is consistent with how limits work for query-based and search run-based seeds.

**Why This Matters:** This gives you more predictable control over seed scope and prevents unexpectedly large seed operations when seeding from broad search results.

***

#### Custom Anonymization Rules Now Available for Sandbox Seeding Jobs

**What Changed:** You can now configure custom anonymization rules when building a seed job, giving you control over how specific fields are masked or transformed when data is seeded into a sandbox.

**Why This Matters:** Data privacy requirements vary by org and team. Custom anonymization lets you tailor seed data to meet your specific policies without relying solely on default masking behavior.

***

### Security & Audit

#### Audit Log Now Available in the Console

**What Changed:** GRAX now maintains an audit log of mutating actions; including changes to backup, archive, and data lake configurations and surfaces that log directly in the console. Contact us for access to this feature.

**Why This Matters:** For teams with compliance or governance requirements, this gives you a clear record of who changed what and when. You no longer need to rely on external tools or logs to track configuration changes within GRAX.

***

### How to Get the Most from These Updates

**Check your archive configurations for related child records.** The new lookup children option is not applied retroactively to existing jobs. Review your recurring archive jobs and consider whether adding related children would make your archive sets more complete.

**Review the audit log if you're managing a shared GRAX environment.** Navigate to the new audit log section in the console to establish a baseline of recent activity before your next compliance review.

**Re-run sandbox seeding jobs if optional parent records were missing.** If you've seeded sandboxes and noticed related records were absent in the target org, the seed graph improvement means a fresh run should now capture those parent records automatically.

***

### Questions or Feedback?

Reach out to your GRAX support contact or customer success team with any questions about these updates.

***

*March 2026*


# February 2026 Release Notes

## GRAX Product Updates

### February 2026

February brought a notable expansion to the record graph with status-based filtering, a long-awaited improvement for Salesforce Knowledge users with full article merging support, and the ability to customize the org connection notice. Formula fields now refresh during seeds and restores, and several storage and restore guardrails were strengthened to make critical workflows more reliable.

***

### Backup & Restore

#### PITR Restore Defaults Stay Separate from Standard Restores

**What Changed:** Saved defaults from a point-in-time restore are now stored separately from standard restore settings. Starting a standard restore no longer inherits point-in-time-specific defaults that were saved in a previous session.

**Why This Matters:** Users who frequently alternate between standard and point-in-time restores now get the correct defaults for each type every time. The restore configuration reflects only what is relevant to the restore type you are initiating.

***

#### Formula Fields Are Now Refreshed During Seeds and Restores

**What Changed:** Formula fields in Salesforce are now recalculated as part of seed and restore operations. The values written to your target org reflect the current formula results rather than the values that were stored at the time the data was captured.

**Why This Matters:** Formula fields in seeded or restored records now reflect current calculated values, so the data in your target org is immediately accurate and ready to use. This is especially important for fields whose values depend on related records or time-based logic, where the stored value and the live calculated value can diverge over time.

***

### Search

#### Search Now Supports Include-Based Filtering

**What Changed:** A new include-based filter option is available in Search, allowing you to scope results by specifying which values or conditions to include rather than exclude.

**Why This Matters:** Include-based filters give you a more direct way to define the exact set of records you are looking for, particularly when working with fields that have many possible values. This complements the existing filter options and expands what you can express in a single search.

***

### Salesforce Knowledge

#### Knowledge Article Merging Now Available for All Organizations

**What Changed:** When seeding or restoring Salesforce Knowledge articles (Knowledge\_\_kav), GRAX now maps articles to their correct counterparts in the target org. This includes support for merged article IDs and proper handling of language variants. Knowledge merging is now enabled across all organizations.

**Why This Matters:** Organizations that manage Knowledge articles can now seed and restore that content with the same reliability as standard Salesforce records. Article IDs are mapped to the correct targets in the destination org, preserving the structure and relationships of your Knowledge base.

***

### User Interface

#### Backend Connection Notice Now Customizable

**What Changed:** The connection notice displayed when GRAX is connected to a Salesforce org can now be customized. Users can update the display name shown in the notice, and administrators can set the banner color. Each user's customization applies to their own view.

**Why This Matters:** For organizations managing multiple orgs or environments, a clearly labeled and color-coded connection notice makes it immediately obvious which org you are working in. This reduces the risk of making changes in the wrong environment and helps teams establish clear visual conventions for production versus sandbox.

***

#### Record Graph Can Now Be Filtered by Record Status

**What Changed:** The relationship graph on record detail pages now includes a status filter. You can choose to display only live records, only archived records, or all records within the graph view.

**Why This Matters:** In organizations with large data volumes, the relationship graph can include a mix of live and archived records that makes it hard to focus on what is currently active. The status filter lets you narrow the graph to exactly the records you need to see, making it more useful for both review and compliance workflows.

***

#### Recurring Activity Navigation Available on Started Activities

**What Changed:** When an activity is in a "started" state, the navigation button linking to its recurring configuration is now visible and accessible.

**Why This Matters:** Previously, you had to wait for an activity to complete before you could navigate to its recurring setup. You can now access and review the recurring configuration at any point during the activity's run, which is helpful when troubleshooting or making adjustments to an in-progress workflow.

***

### Data Lake

#### Data Lake Object Count Now Capped in the Interface

**What Changed:** The interface now enforces a limit on the number of objects that can be added to the Data Lake configuration. Attempts to exceed the limit are blocked with a clear message.

**Why This Matters:** Adding too many objects to the Data Lake can degrade downstream performance and increase processing time significantly. The enforced limit encourages configurations that perform well and prevents accidental over-selection during setup.

***

### Data & Storage

#### Storage Bucket Locked Once It Contains Data

**What Changed:** Once a storage bucket has data written to it, the bucket configuration is now locked. The storage destination cannot be changed while data exists in that location.

**Why This Matters:** Changing the storage bucket on an active GRAX instance is one of the most impactful configuration changes possible, and one of the easiest to make accidentally. Locking the bucket once data is present prevents the kind of misconfiguration that can make existing backup data inaccessible.

***

### How to Get the Most from These Updates

**Customize your org connection notice.** If your team works across multiple Salesforce orgs, take a few minutes to set up distinct colors and labels for each environment. This small change can prevent costly mistakes and is especially valuable for anyone who frequently switches between production and sandbox.

**Try status filtering in the record graph.** If you work with records that have a mix of live and archived relationships, the new status filter gives you a cleaner view. Try filtering to live-only for operational reviews, or to all statuses for compliance and data auditing.

**Knowledge admins: seed and restore are now fully supported.** If your organization manages Salesforce Knowledge and has been waiting for reliable seed and restore support, that is now in place for all orgs. Reach out to your Customer Success contact if you want guidance on incorporating Knowledge into your GRAX workflows.

***

### Questions or Feedback?

Reach out to your GRAX Customer Success contact or visit our support portal for help with any of these updates.

***

*February 2026*


# January 2026 Release Notes

## GRAX Product Updates

### January 2026

January opened the year with two significant platform advances: Azure Managed Identity authentication removes the need for static storage credentials for Azure customers, and inline images in record fields are now served directly from GRAX data. Search also gained relative date support, the Email v2 viewer reached general availability, and Salesforce Files received first-class treatment in the backup process.

***

### Backup & Restore

#### Azure Managed Identity Authentication Now Supported

**What Changed:** GRAX now supports Azure Managed Identities for storage authentication. Organizations using Azure Blob Storage can connect without providing or managing static access keys.

**Why This Matters:** Managed Identities are the recommended approach for securing Azure resource access. This change removes the operational burden of rotating static credentials and reduces the risk associated with long-lived keys. If your organization uses Azure for GRAX storage, you can now migrate to identity-based authentication.

***

#### Point-in-Time Restore Field Selection Limited to Updateable Fields

**What Changed:** The field selection panel in the point-in-time restore flow now shows only fields that Salesforce allows to be updated. Read-only and formula fields are no longer listed.

**Why This Matters:** Seeing fields that cannot be restored was confusing and could lead to restore attempts that could not complete as expected. The field list is now focused on what you can actually act on, making the restore configuration faster and clearer.

***

#### Salesforce Files Now Treated as First-Class Backup Data

**What Changed:** ContentVersion records (Salesforce Files) are now backed up as first-class objects in the backup process, with consistent tracking and inclusion across all organizations.

**Why This Matters:** Files attached to Salesforce records are now captured in every backup. If your organization stores important documents, attachments, or media through Salesforce Files, those are now backed up with the same completeness as your record data.

***

### Search

#### Relative Dates Now Supported in Search Filters

**What Changed:** Date and timestamp search filters now accept relative expressions such as "last 7 days" or "last 30 days" in addition to specific calendar dates.

**Why This Matters:** Most recurring searches are time-relative rather than tied to a specific date. You can now build a search that always covers the last 30 days without having to update the date range each time you run it. This is especially useful for templates and scheduled searches.

***

#### Search Filter Helpers and Modified Field Context Added

**What Changed:** Search now displays additional context alongside certain filters, including helper text to guide field selection and information about when fields were last modified.

**Why This Matters:** This makes it easier to build precise, well-informed queries without leaving the search interface. The additional context is shown inline where it is relevant rather than requiring you to look up field metadata separately.

***

### User Interface

#### Inline Images Now Served from GRAX Data

**What Changed:** HTML field content that includes images now serves those images from GRAX's own stored data rather than linking back to Salesforce. This applies by default across record views.

**Why This Matters:** Images in record fields previously relied on an active Salesforce session to load. They would not display for archived or deleted records, or when a user was not currently logged into Salesforce. Images now load reliably regardless of Salesforce session state, giving you a complete view of your record data at all times.

***

#### Email Viewer v2 Now Generally Available

**What Changed:** The updated email viewer is now the default experience for all users. It provides a more structured, readable presentation of email threads within child record views.

**Why This Matters:** The v2 viewer improves how email conversations are displayed, making it easier to follow threads and find specific messages within a record. All users now have this experience without any additional configuration.

***

#### Smarter HTML Content Updating During Seeds and Restores

**What Changed:** When HTML field values reference Salesforce record IDs (for example, links in rich text fields), GRAX now updates those references using a tag-and-attribute-aware approach rather than simple text replacement.

**Why This Matters:** The previous approach could misidentify or leave behind stale ID references in complex HTML content. The updated approach parses HTML structure before making replacements, so links and embedded references in rich text fields are updated more accurately during seeds and restores.

***

### Archive

#### File Object Relationships Restricted in Archive Activities

**What Changed:** Adding File object relationships directly to Archive activities is now restricted. File-related data should be handled through the dedicated file support path.

**Why This Matters:** Mixing File object relationships into general archive configurations can create unexpected data integrity issues. This guardrail ensures file data is handled through the appropriate path, keeping your archive operations predictable and complete.

***

### How to Get the Most from These Updates

**Azure customers: consider migrating to Managed Identity.** If you currently use static access keys for your Azure storage connection, this is a good time to move to Managed Identity. It removes credential management from your workflow and is the more secure long-term approach.

**Update your recurring search templates to use relative dates.** Templates that were previously hardcoded to specific date ranges can now be updated to use relative expressions like "last 30 days." This keeps them accurate without any maintenance.

**Review how images appear in your record views.** With inline images now served from GRAX data, fields that contain HTML with embedded images should display more completely than before. If your records include rich text with images, take a look at how they now appear.

***

### Questions or Feedback?

Reach out to your GRAX Customer Success contact or visit our support portal for help with any of these updates.

***

*January 2026*


# December 2025 Release Notes

## GRAX Product Updates

### December 2025

December brought a meaningful behavioral change to Search, with AND logic now the default for multi-condition queries, as well as a set of improvements to the restore experience, activity management, and general interface usability. Several smaller refinements across navigation, progress visibility, and layout round out a productive end to the year.

***

### Backup & Restore

#### Point-in-Time Now Applies to Automatic Activities

**What Changed:** Point-in-time context is now threaded through to automatic backup activities, ensuring they operate within the intended time scope when a point-in-time is set.

**Why This Matters:** Automatic activities can now be scoped to a specific point in time, giving you more precise control over what data those activities act on. This is particularly relevant when running targeted restores alongside automated workflows.

***

#### Restore Compare View Sorts Fields by Restorability

**What Changed:** In the field comparison view during a restore, fields are now sorted with restorable fields listed first, followed by the remaining fields in alphabetical order.

**Why This Matters:** The most actionable information is now at the top. When reviewing a restore, you see the fields you can actually update first, rather than having to scan through the full list to find them.

***

### Search

#### Search Now Defaults to AND Logic

**What Changed:** New searches now use AND logic by default, meaning all conditions in the search must be satisfied for a record to appear in the results. Previously, the default was OR logic.

**Why This Matters:** AND logic is more precise and aligns with how most searches are actually intended to work. If you are searching for records that meet multiple criteria simultaneously, you no longer need to manually switch the logic mode. Existing saved searches and templates are not affected by this change.

***

#### Created At Filter Hidden When Field Is Not Present

**What Changed:** The "Created At" filter option in Search is now hidden for object types that do not include a CreatedDate field.

**Why This Matters:** Showing this filter for objects where it has no effect caused confusion and could lead to searches that produced unexpected results. The filter now appears only where it is relevant.

***

#### Search Progress Indicator Refreshed

**What Changed:** The search progress indicator has been updated with a clearer visual design that better communicates how a search is advancing toward completion.

**Why This Matters:** The previous indicator gave limited feedback during longer searches. The updated design makes it easier to read at a glance and reduces uncertainty about whether a search is still running.

***

### User Interface

#### Child Emails Now Support Deep Linking

**What Changed:** You can now open a specific child email directly by including its identifier as a URL parameter. Sharing or bookmarking a link takes the recipient straight to that email thread within the record.

**Why This Matters:** When collaborating on a record review or escalating an issue, you can now point someone to the exact email you are referencing rather than asking them to navigate to it manually.

***

#### Object Options Load Progressively for Large Activities

**What Changed:** For activities with more than 1,000 phases, the Object Options section now loads progressively rather than waiting to load everything at once before displaying.

**Why This Matters:** Large activities would previously cause a noticeable delay before the Object Options section became usable. Progressive loading keeps the interface responsive and lets you start reviewing options while the rest continues to load.

***

#### Improved SSO Error Messaging for Insufficient Permissions

**What Changed:** When a user attempts to log in via SSO without the required permissions, the error message now clearly identifies what permission is missing and what needs to happen for access to be granted.

**Why This Matters:** Vague SSO errors slow down onboarding and IT support. A specific, actionable message gets users to the right person faster and reduces back-and-forth between users and administrators.

***

### How to Get the Most from These Updates

**Review your saved search configurations.** The new default of AND logic applies to searches created going forward. If you have team members building new searches, let them know that multi-condition searches now work as AND by default, which may be a welcome change or one worth explaining depending on their use case.

**Use the new deep link capability for email threads.** If your team does record reviews in GRAX and references specific emails, you can now share a direct link to the thread. This works especially well in combination with Search to surface the record and then navigate directly to the relevant communication.

**Check your large activities.** If you manage activities with many phases, Object Options now loads progressively. The experience for large activity configurations should feel noticeably more responsive.

***

### Questions or Feedback?

Reach out to your GRAX Customer Success contact or visit our support portal for help with any of these updates.

***

*December 2025*


# November 2025 Release Notes

## GRAX Product Updates

### November 2025

November's headline is the addition of PostgreSQL as a Data Lake destination, opening up a new class of downstream workflows for teams that run on Postgres-based infrastructure. The month also brought meaningful improvements to search (date fields, progress visibility), the archive chart, and a set of data integrity enhancements that make archive and restore operations more reliable across all organizations.

***

### Archive

#### Files Now Included in the Archive Activity Chart

**What Changed:** The Archive activity chart now displays file-related data alongside record data, giving you a complete view of what your archive activity is processing.

**Why This Matters:** If your archive activities include files, you can now see file volumes alongside record counts in the same chart. This gives you a more complete picture of the scope and health of each archive run.

***

#### Archive ModStamp Cutoff Now Active for All Organizations

**What Changed:** The modification timestamp cutoff for archive activities is now enabled for all organizations. This prevents GRAX from re-archiving records that have not been modified since the last archive run.

**Why This Matters:** Archive runs are now more efficient across the board. Records that have not changed are skipped automatically, reducing processing time and resource usage without any configuration needed on your part.

***

#### Archive Now Validates Required Relationships for Newly Added Parents

**What Changed:** When GRAX identifies newly added parent records during an archive, it now checks whether the required relationships between those records are in place before proceeding.

**Why This Matters:** This ensures that archived record hierarchies remain consistent and complete. Parent records are only included when their relationships meet the expected structure, reducing the chance of incomplete archive chains.

***

#### Archive Checks Record Deletion Status Before Skipping

**What Changed:** Before skipping a record during an archive operation, GRAX now checks whether that record has already been deleted. This allows already-deleted records to be handled with the appropriate cascade logic.

**Why This Matters:** Records that were deleted between archive runs are now processed through the correct deletion path rather than being silently skipped. This keeps your archived data more accurate and complete.

***

### Search

#### Date and Timestamp Filters Now Accept Empty Values

**What Changed:** When building a search filter on a date or timestamp field, you can now leave the value blank to find records where that field has no value set.

**Why This Matters:** Searching for records with missing date data (for example, contacts with no close date or opportunities with no last activity date) is now possible directly from the search interface, without requiring a workaround.

**Note:** A helper message now appears in the search builder to let you know when leaving a date or timestamp field blank is a valid option.

***

#### Search Progress Now Visible in Real Time

**What Changed:** A progress indicator now appears while a search is running, showing that work is actively happening.

**Why This Matters:** For searches that take longer to complete, this makes the experience much clearer. You can see the search progressing rather than waiting with no feedback, which reduces the temptation to re-run or navigate away.

***

### Seeding

#### S3 Region Now Locked in Storage Configuration

**What Changed:** When configuring an S3 storage destination, the selected region is now locked once it is set, preventing accidental changes that could redirect data.

**Why This Matters:** Changing the S3 region on an existing storage configuration can cause serious data accessibility issues. Locking the region once set ensures that your storage destination remains stable and intentional.

***

### User Interface

#### Select All / None for Object Relationships

**What Changed:** The object relationships tab in activity configuration now includes Select All and None buttons, letting you quickly include or exclude all available relationships in a single click.

**Why This Matters:** For activities that span many object types, manually checking or unchecking individual relationships is time-consuming. The new controls let you start from a full selection and remove what you do not need, or start from none and add only what you want.

***

#### Backup Status Notification Clarity Improved

**What Changed:** The backup status notification banner has been updated with a clearer visual hierarchy and more direct messaging about what action is needed.

**Why This Matters:** The backup nag is important to act on, and a clearer design makes it easier to understand what it is telling you and what to do about it. The update reduces the chance of the notification being dismissed without the underlying issue being addressed.

***

### How to Get the Most from These Updates

**Explore PostgreSQL as a Data Lake destination.** If your team runs analytics or reporting on Postgres, you can now connect your Data Lake output directly. Reach out to your Customer Success contact if you want help getting started.

**Use empty-value date filters in your searches.** The ability to search for records with blank date fields is particularly useful for data quality reviews. Try it on fields like close dates, last activity dates, or any date field where missing values indicate incomplete records.

**Review your archive activity charts.** Now that files are included, you may see different totals than before. This is expected and gives you a more complete picture of what each archive run is doing.

***

### Questions or Feedback?

Reach out to your GRAX Customer Success contact or visit our support portal for help with any of these updates.

***

*November 2025*




---

[Next Page](/llms-full.txt/1)

