Heroku External Objects
Last updated 31 August 2020
Heroku External Objects is available as part of Heroku Connect. It provides an oData wrapper for a Heroku Postgres database that has been configured for use with Heroku Connect. This feature allows other web services to retrieve data from within the specified Heroku Postgres database using RESTful endpoints generated by the wrapper.
Used in tandem with Salesforce Connect, the feature permits data in a Heroku Postgres database to be represented in a Salesforce deployment, where it can be viewed (including within Apex and Visualforce pages), searched, and related to other objects. It cannot be used in standard reports as the data is only available by reference.
Service Authentication
External Objects service endpoints are protected by basic authentication. Once the service is enabled, credentials can be viewed, reset, and revoked from the External Objects settings page.
When you reset your credentials, there is a 10 minute window in which both your old credentials and your new credentials will be accepted. This allows you to update the credentials of your consuming services without incurring downtime.
Resource Configuration
When the External Objects service is active for a connection, a list of available tables and views will appear in the External Objects settings page. Tables and views across all schemas within the associated connection’s database will be available, including those schema not actively managed by Heroku Connect as part of the synchronization service. Any of these tables or views can be enabled or disabled as a resource in the External Objects service by selecting the corresponding checkbox in the settings page.
To be enabled as an External Objects resource, tables must contain a primary key column. Views must have a column named id
.
Rate limits
The External Objects service is rate-limited at 20,000 requests per service, per hour for the shield
, enterprise
, or danketsu
paid plans; rate limits can be increased on request. For the demo
plan, the limit is 1,000 requests per service, per hour. Attempting to access services after this limit has been reached will result in a 429 Too Many Requests
error. The response message will also contain information about when to expect to be able to make another API request. Rate limit throttles reset at the top of each hour.
{"message":"Request was throttled. Expected available in 1000.0 seconds."}
Logging
Administrative changes made to configuration such as credential reset and revocation, and database object inclusion and exclusion are logged as part of Heroku Connect’s Audit Messages.
Heroku External Objects produces logs of its request and ratelimit activity, which you can access from your log drain (see also, Heroku Connect Application Logging). It generates one message to capture the ratelimit that has been used and the total ratelimit for the service which would look like:
2020-02-12T19:13:07+00:00 app[herokuexternalobjects]: addon_id=82b1c244-592d-4165-99e7-89a270459752 object_type=sync object_id=55cae68a-0628-4497-bbcd-b32cf3b7c5cf state=IDLE request_id=3d4917bc-d255-2c69-4e3d-fa4f8a2a733f method=GET path=/odata/v4/fefbdf7b43794182af6cb7c1fc04fbf9/schema$lead at=ratelimit ip=127.0.0.1 ratelimit_used=38 ratelimit=22000 user_agent=python-requests/2.11.1 level=info
Heroku External Objects also generates a log message for the response it provides to the caller:
2020-02-12T19:13:07+00:00 app[herokuexternalobjects]: addon_id=82b1c244-592d-4165-99e7-89a270459752 object_type=sync object_id=55cae68a-0628-4497-bbcd-b32cf3b7c5cf state=IDLE request_id=3d4917bc-d255-2c69-4e3d-fa4f8a2a733f method=GET path=/odata/v4/fefbdf7b43794182af6cb7c1fc04fbf9/schema$lead at=response ip=127.0.0.1 service=82.94556713104248ms status=200 user_agent=python-requests/2.11.1 level=info
These logs can be correlated by the request_id
.
Supported Data Types
Heroku External Objects supports the following PostgreSQL data types:
bigint
boolean
bytea
character
/character varying
date
double precision
integer
numeric
real
smallint
text
time
timestamp
uuid
If you enable a table or view that has an unsupported data type, the unsupported field will not be included in results.
Limitations
Generated identity defaults for Primary Key
PostgreSQL added support for an alternative to using SERIAL
or BIGSERIAL
by creating a primary key column with GENERATED BY DEFAULT AS IDENTITY
or GENERATED ALWAYS AS IDENTITY
. These defaults are not supported by Heroku External Objects and will cause creation of new records to fail. Retrieving, updating, and deleting will work.
Case-insensitive search
Searches in Salesforce for data in External Objects are done in a case-sensitive manner. Case-insensitive searching is currently not supported by Heroku External Objects.
Batch Apex
Using Batch Apex in Salesforce to query Heroku External Objects is currently not supported.
Global Search
Heroku External Objects does not presently support Global Search queries from Salesforce Connect.
Query Time Limit
Queries generated by Heroku External Objects must complete in 20 seconds or less, otherwise Heroku External Objects will return a 530 response to Salesforce Connect.
Compress Requests
Enabling the Compress Requests option for an External Data Source in Salesforce is currently not supported.
Estimated odata.count Value
Counting the rows in a Postgres table is slow and can be intense for a database. As a result, when returning paginated results for a query, Heroku External Objects returns one more than the number of records to indicate that there are more results.
Tables Without Columns Are Unsupported
While PostgreSQL allows users to create a table without a column, it’s not compliant with the SQL specification and semantically ambiguous in the context of Heroku External Objects. As a result, Heroku External Objects does not support (or display) tables that do not have columns.