# Connect Reverse ETL Source to Salesforce Bulk Upload


This guide takes you through the steps to connect a [Reverse ETL source]({{< ref "sources/reverse-etl/" >}}) to your Salesforce Bulk Upload destination.

## Setup 

1. Set up and configure your Reverse ETL source.
2. In the **Overview** tab of the source page, click **Add destination** > **Create new destination**. You can also select an already-configured destination here.
3. From the list of destinations, select **Salesforce Bulk Upload** and click **Continue**.
4. Specify a unique name to identify this destination in RudderStack.
5. In the **Event delivery account** section, click **Select** to choose an existing Salesforce account from the list, then skip to **Step 7**. 
6. To add a new account, click **Add account**, select **OAuth**, and specify the following settings:

| Setting | <div style="width: 350px;">Description</div> |
| :----| :-----|
| Account Name | Specify a unique account name |
| Environment type | Select the Salesforce environment type — **Production** or **Sandbox** |
| Connect account | Click **Connect account**, sign in to Salesforce, and give RudderStack the required permissions to access your Salesforce account. |

7. Click **Continue** to configure the [mapping settings](#mapping-settings).

## Mapping settings 

Under **Where do you want to sync data to?**, select the Salesforce object. Click **Reload objects** to refresh the list of available objects.

### Sync mode

RudderStack supports only [Upsert mode]({{< ref "data-pipelines/reverse-etl/developer-guides/sync-modes.md#upsert-mode" >}}) for this integration.

### Cursor column settings

| Setting | <div style="width: 350px;">Description</div> |
| :----| :-----|
| Use Cursor Column | Toggle on to use a [cursor column]({{< ref "data-pipelines/reverse-etl/developer-guides/cursor-column-support.md" >}}) for incremental syncs |
| Cursor Column | Specify the appropriate cursor column from the dropdown |

### Map identifiers

| Setting | <div style="width: 350px;">Description</div> |
| :----| :-----|
| Choose identifier | Select a warehouse column to uniquely identify your records and map it to the relevant Salesforce field. |
| Map field | Configure which warehouse column maps to which Salesforce field. |

{{< image src="images/event-stream-destinations/salesforce-bulk-upload/mappings.webp" alt="Mapping settings" >}}

## Sync settings

{{< customreadfile "/includes/retl/schedule-syncs.md" >}}

#### Sync observability settings

{{< customreadfile "/includes/retl/sync-observability-settings.md" >}}

## Enable sync

Once the setup is complete, click **Enable** to activate your destination and start syncing data at the specified interval. 

{{< image src="images/event-stream-destinations/salesforce-bulk-upload/enable-destination.webp" alt="Enable Salesforce Bulk Upload destination" >}}

## Null value handling

Upsert syncs handle missing and null mapped values differently:

| Warehouse / synced value | CSV cell | Salesforce behavior on update |
| :--- | :--- | :--- |
| Explicit `null` | `#N/A` | Clears the field |
| Field absent from the synced data | Empty | Leaves the existing value unchanged |

{{< info >}}
Salesforce Bulk API ignores empty cells on update and only clears a field when the cell is `#N/A`. See [Valid CSV Record Rows](https://developer.salesforce.com/docs/atlas.en-us.api_asynch.meta/api_asynch/datafiles_csv_valid_record_rows.htm).
{{< /info >}}

## FAQ

#### Why can't I add a Reverse ETL source from the destination page?

The Reverse ETL feature supports only source-driven pipeline configuration. It means that you must configure a Reverse ETL source in RudderStack and then connect it to a new or existing destination. Note that this destination should not be connected to any other source.

See [Reverse ETL FAQ]({{< ref "data-pipelines/reverse-etl/developer-guides/faq.md" >}}) for more information.

<br />
