🧩 Summary
Per the comment below, we rely on the assumption of a fixed email as the primary user identifier in these places:
- In code, as a foreign key and the primary key to get-or-create a user by when they log in
- In customer.io, which is what we use to send almost all emails to users
- In Keycloak (where we want to keep login-by-email, but enable the
update-email setting)
- In PostHog, we use email as the
distinct_id for users
- In the CRM base
- In automations throughout other bases (mostly sending things to customer.io, but some other cases)
We want to migrate all of these to handle potentially changing emails (brief summary, more detail will be in sub-issues etc):
- In code: We can use the user id (i.e. the
id of the User record in the Applications base) as the foreign key. For the auth object itself and the initial get-or-create of the User, we can use the sub property that comes from Keycloak.
- In customer.io: Roughly speaking, we can run an Identify API call when someone updates their email, and then leave the existing automations as-is (which will pick up the new email, and a continuous history for the user will be preserved in customer.io). There are some edge cases here: emails relating to a specific application form (where we should keep the form email), and newsletter subscribers
- In Keycloak: Enable the
update-email flow (verify-new-then-swap) so email becomes mutable, and treat the immutable sub as the identity.
- In PostHog: Use the stable user id as the
distinct_id and set the email as a person property (so people stay searchable by email).
- In the CRM base: Keep Primary email as the human lookup key — the CRM also holds people with no account, so email has to stay the key here — but make matching dedupe on ANY known email (not just the current primary), and carry the stable user id on the Person where possible.
- In automations throughout other bases: Update on a case my case basis depending on what they do
I'll break this down into sub-issues which plan out the individual changes more concretely and what-blocks-what.
✅ Definition of done
The above consumers of email are migrated to support potentially changing emails
📌 Notes / Designs
No response
🧩 Summary
Per the comment below, we rely on the assumption of a fixed email as the primary user identifier in these places:
update-emailsetting)distinct_idfor usersWe want to migrate all of these to handle potentially changing emails (brief summary, more detail will be in sub-issues etc):
idof the User record in the Applications base) as the foreign key. For theauthobject itself and the initial get-or-create of the User, we can use thesubproperty that comes from Keycloak.update-emailflow (verify-new-then-swap) so email becomes mutable, and treat the immutablesubas the identity.distinct_idand set the email as a person property (so people stay searchable by email).I'll break this down into sub-issues which plan out the individual changes more concretely and what-blocks-what.
✅ Definition of done
The above consumers of email are migrated to support potentially changing emails
📌 Notes / Designs
No response