← Back to Integration & Data
INTG-008 Integration & Data 18 min read For: Salesforce Architects & Tech Leaders

Heroku Connect: When It's the Right Answer and When It Isn't

Heroku Connect provides bidirectional sync between a Heroku Postgres database and Salesforce. It solves a specific problem elegantly. But it's often proposed as a general-purpose integration solution when it isn't — and used incorrectly it creates data inconsistency problems that are painful to diagnose.

VS

Vishal Sharma

Salesforce Architecture Specialist · Updated May 2026

What you will learn...
  • How Heroku Connect works under the hood — the sync mechanism, the streaming API dependency, and the Postgres schema it creates
  • The correct use case: Heroku apps that need Salesforce data as a Postgres-accessible data layer
  • The sync latency characteristics and what "near real-time" actually means in practice
  • Conflict resolution: what happens when both Salesforce and Postgres are updated simultaneously
  • The architectural limitations that make Heroku Connect the wrong choice for certain patterns
  • Alternatives to Heroku Connect for common use cases where it falls short

What Heroku Connect Actually Does

Heroku Connect is a managed sync service that maintains a replicated copy of Salesforce objects in a Heroku Postgres database. It maps selected Salesforce objects (standard and custom) to corresponding Postgres tables, synchronises writes in both directions, and handles authentication and API communication with Salesforce automatically. A developer building a Heroku application can query Salesforce data using standard Postgres SQL without calling the Salesforce API directly.

The sync mechanism uses Salesforce's Streaming API (CDC or PushTopics) for Salesforce-to-Postgres direction — changes in Salesforce are captured as streaming events and applied to the Postgres tables. For Postgres-to-Salesforce direction, Heroku Connect polls the Postgres tables for rows with a modified flag (using a trigger-managed _hc_lastop column) and pushes changes to Salesforce via the REST API. This polling interval is configurable but defaults to a few seconds.

The Postgres schema created by Heroku Connect is not user-controlled — it mirrors the Salesforce object structure. Each Salesforce object gets a Postgres table with columns matching the mapped Salesforce fields, plus Heroku Connect metadata columns (_hc_err, _hc_lastop, _hc_lastop_ts). These metadata columns track sync status and must not be modified by application code — doing so will corrupt the sync state.

💡
Heroku Connect is a Heroku product, not a Salesforce product: Heroku Connect requires a Heroku Postgres add-on and a Heroku Connect plan. It does not work with arbitrary Postgres instances — the Postgres database must be the Heroku-managed Heroku Postgres add-on. If your application runs on AWS RDS Postgres or another managed Postgres, Heroku Connect is not available without migrating the database to Heroku Postgres.

The Right Use Case for Heroku Connect

Heroku Connect solves one problem well: a Heroku-hosted application that needs to read and write Salesforce data using SQL and the Postgres query model, without the application developers needing to understand the Salesforce API. A web application built with Ruby on Rails, Django, or Node.js can use its ORM to query the Heroku Connect-managed Postgres tables as if they were native application tables — no Salesforce API client library required, no OAuth flow to manage, no SOQL to write.

The canonical use case is a customer portal or a high-traffic web application that needs to display and update Salesforce records at scale. The Heroku app reads Account and Contact data from Postgres at high read throughput (Postgres handles thousands of concurrent reads; Salesforce REST API has rate limits). Writes from the portal go to Postgres first, and Heroku Connect propagates them to Salesforce asynchronously. The result is a read-scalable architecture with Salesforce as the system of record.

A secondary good use case is rapid prototyping and development. Development teams building against a Salesforce org can use Heroku Connect to get a queryable Postgres replica without learning the Salesforce API surface. This reduces the barrier to entry and accelerates development cycles for Heroku-native teams. The trade-off is that this convenience creates a dependency that is hard to remove when the application grows beyond the Heroku platform.

Sync Latency and Real-World Performance

Heroku Connect documentation describes the sync as "near real-time." In practice, Salesforce-to-Postgres sync latency is typically 5-30 seconds for individual record changes and can be minutes during high-volume change periods when the streaming event queue backs up. Postgres-to-Salesforce latency is controlled by the polling interval — default of a few seconds, but actual API call latency and Salesforce processing time add to this.

The critical implication: if an application writes to the Heroku Connect Postgres table and then immediately queries Salesforce for the updated record, the Salesforce record may not yet reflect the Postgres change. Similarly, if Salesforce triggers run and change the record further after a Heroku Connect write arrives, the Postgres table will not reflect the trigger-modified values until the next Salesforce-to-Postgres sync cycle. This "eventual consistency" window must be understood and designed around in applications that depend on immediately consistent state.

Under high load — a batch operation creating 10,000 Salesforce records simultaneously — the Salesforce-to-Postgres sync can lag by minutes as the streaming event queue processes the backlog. Applications that query the Postgres tables expecting real-time accuracy during bulk operations will see stale data. Monitor the _hc_err column for sync errors and the Heroku Connect dashboard's sync health metrics to detect and alert on sync lag.

⚠️
Conflict resolution favors the last writer: When both Salesforce and the Postgres table are updated for the same record within the sync latency window, Heroku Connect resolves the conflict by last-write-wins. The system that wrote most recently (determined by the sync cycle timing) will have its values persist. This means concurrent edits can silently overwrite each other. Design application workflows to avoid concurrent bidirectional updates to the same record.

When Heroku Connect Is Wrong for the Job

Heroku Connect is wrong when the application needs guaranteed write consistency between Salesforce and the application database. Because the sync is asynchronous, there is no transaction boundary that spans both systems. If a Heroku app writes an order record to Postgres and the subsequent Heroku Connect sync to Salesforce fails (due to a validation rule, a field that doesn't exist, or an API error), the Postgres record exists but the Salesforce record does not. The _hc_err column captures the error, but the application must explicitly check and handle these sync failures.

Heroku Connect is wrong for high-write-volume scenarios where Postgres writes must reach Salesforce within seconds. The polling-based Postgres-to-Salesforce sync, combined with Salesforce API processing time, means write propagation is inherently asynchronous. A payment processing application that writes transaction records to Postgres and expects them in Salesforce before the next processing step completes will encounter race conditions.

It is also wrong for non-Heroku application architectures. An application running on AWS EC2, Azure App Service, or Google Kubernetes Engine cannot use Heroku Connect — the Postgres database must be a Heroku Postgres add-on. Attempting to work around this by exposing Heroku Postgres externally introduces latency, security complexity, and a persistent infrastructure coupling to Heroku that limits architectural flexibility.

Alternatives for Common Use Cases

For read-scalable Salesforce data access from a web application that does not run on Heroku, the appropriate alternative is a dedicated read replica populated from Salesforce via Fivetran or a custom CDC subscriber that writes to the application's native database. This provides the same Postgres-queryable Salesforce data without the Heroku dependency.

For bidirectional sync with conflict management, MuleSoft or a custom integration using Platform Events provides explicit conflict resolution logic (business-rule-driven, not last-write-wins) and transactional error handling. This is more complex to implement than Heroku Connect but appropriate when data consistency guarantees matter.

For Heroku applications specifically that need synchronous Salesforce writes (not asynchronous), the application should call the Salesforce REST API directly for writes — using a Salesforce API client library — and use Heroku Connect only for read access to the Postgres replica. This hybrid pattern gets the read scalability benefit of Heroku Connect while ensuring writes to Salesforce are synchronous and immediately consistent.

Key Takeaways

  • Heroku Connect maintains a Postgres replica of Salesforce objects in a Heroku Postgres database, using Streaming API for Salesforce-to-Postgres sync and polling for Postgres-to-Salesforce write propagation.
  • The correct use case is Heroku-hosted applications that need high-read-throughput access to Salesforce data using SQL, without requiring the application team to learn the Salesforce API.
  • Sync latency is typically 5-30 seconds in each direction — applications must design for eventual consistency rather than assuming immediate read-after-write accuracy.
  • Conflict resolution is last-write-wins — concurrent edits to the same record from both Salesforce and Postgres can silently overwrite each other. Design workflows to prevent concurrent bidirectional updates.
  • Heroku Connect is wrong for applications requiring guaranteed write consistency, high-throughput write propagation within seconds, or applications running outside the Heroku platform.
  • For non-Heroku applications, Fivetran CDC or a custom streaming subscriber provides a Postgres replica without Heroku dependency. For synchronous Salesforce writes, use the Salesforce REST API directly alongside Heroku Connect reads.

Test Your Understanding

1. A Heroku application writes a Case record to the Heroku Connect Postgres table. A Salesforce Flow triggers on the Case and updates a custom field. The application queries the Postgres table 3 seconds later. What will it see?

The Case record with the Flow-updated custom field value — Heroku Connect syncs in real-time so the Flow update is immediately visible
The original Case values without the Flow update — the Postgres-to-Salesforce write takes a few seconds, the Flow runs in Salesforce, and the Salesforce-to-Postgres sync of the Flow update may take another 5-30 seconds. The application will see eventual consistency, not immediate consistency.
An empty row — the Case does not appear in Postgres until the Salesforce record confirms the write

2. An architect proposes using Heroku Connect to provide a Salesforce data replica for a Django application running on AWS. What is the fundamental problem with this proposal?

Django does not support Postgres connections, so the application cannot query the Heroku Connect-managed tables
Heroku Connect requires Heroku Postgres — the application's database must be a Heroku-managed Postgres instance. A Django application on AWS using RDS Postgres cannot use Heroku Connect.
AWS and Heroku have network restrictions that prevent cross-cloud Postgres connections required by Heroku Connect

3. A Heroku Connect sync fails because a Case record written to Postgres has a Status value that violates a Salesforce validation rule. Where is this error captured and how should the application handle it?

Heroku Connect rolls back the Postgres write — the Case record disappears from the Postgres table so the application knows the sync failed
The error is stored in the _hc_err column of the Postgres Case row — the application must query for rows where _hc_err IS NOT NULL to detect sync failures and implement a remediation workflow to correct and re-sync the rejected records
Heroku Connect sends a webhook notification to the application when a sync failure occurs, automatically triggering the application's error handler

Discussion & Feedback