- 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.
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.
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?
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?
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?
Discussion & Feedback