The ExternalLink entity is a cornerstone of the OpenFaith synchronization engine. It acts as the "Rosetta Stone," enabling robust and reliable mapping between entities within the OpenFaith Canonical Data Model (CDM) and their corresponding records in various external Church Management Systems (ChMS) or other applications.
This dedicated entity is crucial for building a scalable and maintainable sync system by directly addressing common challenges encountered in data integration, such as managing disparate ID systems and optimizing data operations.
-
Conflating Internal and External IDs:
- Problem: Relying on an
externalIdfield directly on core OpenFaith entities (e.g.,Person.externalId) creates several issues:- It tightly couples the OpenFaith entity to a single external system. What if a Person needs to link to PCO and CCB?
- It makes it difficult to assign a stable, internally generated OpenFaith ID if the
externalIdis used as the primary means of identification during imports.
- Solution with
ExternalLink: OpenFaith entities always have their own unique, internally generatedid. TheExternalLinktable separately manages the many-to-many relationships between OpenFaith IDs and any number of(adapter, externalId)pairs. This keeps the core OpenFaith model clean and independent.
- Problem: Relying on an
-
Inefficient Data Lookups (Excessive Reads During Sync):
- Problem: Without a dedicated mapping table, determining if an incoming external record already exists in OpenFaith (and what its internal ID is) often requires "fuzzy" searching on OpenFaith tables based on attributes like email or name. For every incoming record, this could mean:
SELECT * FROM People WHERE email = ? AND name = ? ...This is read-intensive, slow for large datasets, and prone to errors (multiple matches, no matches for legitimate links). Updating an existing record also first requires finding it.
- Solution with
ExternalLink:- Incoming Changes (Webhooks/Polls): A direct, indexed lookup on
ExternalLinksusing(adapter, externalId)instantly provides theentityId. This is a single, highly efficient query. - Outgoing Changes: A direct, indexed lookup on
ExternalLinksusingentityIdquickly retrieves all associated external system IDs for propagation.
- Incoming Changes (Webhooks/Polls): A direct, indexed lookup on
- Problem: Without a dedicated mapping table, determining if an incoming external record already exists in OpenFaith (and what its internal ID is) often requires "fuzzy" searching on OpenFaith tables based on attributes like email or name. For every incoming record, this could mean:
-
Complex Logic for Initial Sync into Pre-existing Datasets:
- Problem: If an organization already has data in OpenFaith and wants to sync a new external ChMS, merging the datasets and establishing links without creating duplicates or missing connections is highly complex if relying only on attribute-based matching.
- Solution with
ExternalLink(Unified Sync with Smart Conflict Resolution):- Unified Operation: The system uses a single operation with intelligent conflict resolution via
ON CONFLICT DO UPDATEto handle both initial sync and incremental updates efficiently. - Smart Entity ID Management: New external records get assigned OpenFaith entity IDs immediately, while existing records preserve their existing entity links during conflicts.
- Conditional Processing: The system only updates
lastProcessedAtwhen external records have actually changed, optimizing performance.
- Unified Operation: The system uses a single operation with intelligent conflict resolution via
-
Difficulty Managing Multi-System Identities:
- Problem: How do you know if PCO Person "123" and CCB Person "ABC" are the same individual in your system without a central mapping?
- Solution with
ExternalLink: If bothExternalLinkrecords(pco, 123)and(ccb, ABC)point to the sameentityId, the system knows they represent the same canonical person.
A typical ExternalLink record would include:
_tag(Discriminated union tag, set to "externalLink")orgId(The OpenFaith organization this link belongs to)entityId(Foreign Key to the ID of the OpenFaith entity, e.g.,Person.id)entityType(The_tagof the OpenFaith entity, e.g., "person", "group")adapter(A unique identifier for the external system, e.g., "pco", "ccb", "breeze")externalId(The unique identifier of the record within the external system)lastProcessedAt(Timestamp indicating when this link was last involved in a successful sync operation)syncing(Boolean flag indicating whether this external link is currently being synchronized)updatedAt(Timestamp from the external system indicating when the record was last modified)- Soft Delete:
deletedAt,deletedBy
Primary Key:
- The combination of (
orgId,adapter,externalId) forms the composite primary key for the ExternalLink table. There is no separateidfield.
Critical Constraint: A UNIQUE constraint is enforced on (orgId, adapter, externalId) to ensure that a specific external record can only be linked once per organization.
The OpenFaith implementation uses an efficient unified approach that combines initial sync and incremental updates into a single operation:
INSERT INTO external_links (orgId, adapter, externalId, entityId, entityType, ...)
VALUES (...)
ON CONFLICT (orgId, adapter, externalId) DO UPDATE SET
lastProcessedAt = CASE
WHEN EXCLUDED.updatedAt IS DISTINCT FROM external_links.updatedAt
THEN EXCLUDED.lastProcessedAt
ELSE external_links.lastProcessedAt
END,
updatedAt = EXCLUDED.updatedAtKey Benefits of This Approach:
-
Entity ID Preservation: Existing
entityIdvalues are preserved during conflicts, maintaining established links between external and OpenFaith entities. -
Conditional Processing:
lastProcessedAtis only updated when the external record has actually changed, avoiding unnecessary processing. -
Atomic Operations: The entire sync operation is atomic, ensuring data consistency.
-
Efficient Updates: No need for separate lookup queries - the conflict resolution handles both new records and updates seamlessly.
- External Data Ingestion: External records are inserted into
ExternalLinkswith new OpenFaith entity IDs - Conflict Resolution: Existing records preserve their entity links while updating timestamps
- Entity Processing: Only records that were actually updated (based on
lastProcessedAtcomparison) are processed for entity updates
- Clean Core Model: OpenFaith entities maintain their own independent ID system.
- Multi-System Linking as a First-Class Citizen.
- Improved Performance: Significantly reduces database reads during routine sync operations by enabling direct ID-based lookups once links are established.
- Scalability: Handles large datasets more effectively with unified operations.
- Clarity and Traceability: Provides a clear audit trail of how entities are connected.
- Foundation for Advanced Features: Merging duplicates, complex conflict resolution.
- Efficient Conflict Resolution: Smart handling of both initial sync and incremental updates in a single operation.
The current implementation pattern efficiently handles both scenarios:
- Initial Sync: New external records get assigned OpenFaith entity IDs and are processed for entity creation
- Incremental Updates: Existing records preserve their entity links while updating timestamps and processing only changed records
This unified approach eliminates the need for explicit phased operations while maintaining all the benefits of the ExternalLinks pattern.
In summary, the ExternalLink entity is not just a mapping table; it's a strategic component designed to optimize performance, ensure data integrity, and simplify the complex logic required for robust, bi-directional, and multi-system synchronization within the OpenFaith platform.