Soft Delete Model
The Data Share pipeline uses a soft-delete model internally. When a record is deleted
in Affinity, it is marked as deleted in the pipeline rather than being physically removed.
Note: Soft deletes are cleaned after 7 days, deleted records will only be visible in the share for 7 days after deletion.
Merges
When two persons or two companies are merged in Affinity, one record survives and the other is
removed. The share reflects a merge as a delete of the removed record plus updates to the surviving
record and its associations. There is no separate merge event or merge flag in the share.
Persons
- The surviving person keeps its
id. Its row in persons is updated and last_updated_at
advances.
- The removed person’s row in
persons is marked is_deleted = TRUE, then removed from the share
after 7 days like any other delete.
- Associations that referenced the removed person (
companies_persons, list_entries_persons,
notes_persons, opportunities_persons, chat_messages_persons) are re-pointed to the surviving
id. Each association row keeps its own id. Where the surviving person already had an
equivalent association, the duplicate row from the removed person is marked is_deleted = TRUE
instead.
- Email associations are not re-pointed. Rows in
emails_persons for the removed person are marked
is_deleted = TRUE, and new rows with new id values are created for the surviving person once
its email addresses are matched to the same emails. This matching runs shortly after the merge, so
there can be a short window where an email has no association to the surviving person.
emails_companies is derived from emails_persons and refreshes after those rows update.
- Meeting and call associations (
meetings_persons, calls_persons) are re-pointed like other
associations when the surviving person is external. When an external person is merged into an
internal person, only manually logged meetings and calls are re-pointed. Synced calendar events
are re-matched to the surviving person the same way emails are, so those rows are re-created with
new id values.
- Custom field values from the removed person are carried over to the surviving person where the
surviving person has no value for that field, and appear in its
custom_fields.
Companies
Company merges behave the same way as person merges, with one addition: some merges produce a
new company id.
- Merging two tenant-specific companies (
is_global = FALSE): the surviving company keeps its
id, and the removed company is marked is_deleted = TRUE.
- Merging a global company into a tenant-specific company: the tenant-specific company keeps
its
id. If the global company was in your companies table, its row is marked
is_deleted = TRUE.
- Merging a tenant-specific company into a global company where the tenant-specific company has
no extra domains: the global company keeps its
id, and the tenant-specific company is marked
is_deleted = TRUE. If the global company was not previously in your companies table, it
appears as a new row.
- Merging two global companies, or merging a tenant-specific company with extra domains into
a global company: Affinity creates a new tenant-specific company with a new
id, and both
original companies are marked is_deleted = TRUE.
In every case, associations (companies_persons, list_entries_companies, notes_companies,
opportunities_companies) are re-pointed to the surviving or newly created company id, and custom
field values are carried over where the surviving company has no value for the field.
emails_companies, meetings_companies, calls_companies, and chat_messages_companies are
derived from the person and email-address associations rather than stored against the company, so
they are not re-pointed directly and refresh once those underlying associations update.
The share does not expose a mapping from a removed id to the surviving id. If you keep
references to Affinity IDs in your own systems, watch for rows that flip to
is_deleted = TRUE and match them to the surviving record while the removed row is still
present in the share. Persons can be matched on primary_email_address or email_addresses;
companies can be matched on domain or domains.