The cleanest path is to keep the current Airtable, Chargebee, Customer.io, and Discord flows, then add one root Customer Identity Profiles table with a stable profile_id. That profile ties each customer's Chargebee customer records, the billing email on each customer, subscriptions, and access history together. The profile stores one active primary_discord_id for product access, while the billing email on each Chargebee customer stays available for purchases, billing, and recovery.
Customers can log in with Discord or email. Discord is the recommended path for product access, while email remains important for purchases, billing, and recovery.
The Customer Identity Profile becomes the account root. Multiple Chargebee customer records, their billing emails, Discord identity, and subscriptions can all connect without creating fragmentation.
The current tables stay focused on what they already do, while the profile table gives staff and automation one stable customer record to link back to.
This helps reduce missed cancellations, Discord access discrepancies, and support confusion by making the system treat the customer as one person with one primary Discord identity and multiple linked billing records, instead of multiple disconnected Chargebee records.
If a Discord ID exists, resolve the Customer Identity Profile from Discord first. If a new purchase creates or uses a different Chargebee customer record or billing email but later links the same Discord ID, attach that Chargebee customer, its billing email, and subscription to the existing profile. If no Discord ID exists yet, create or stage a profile from the Chargebee customer and billing email, then require Discord linking before full product access. A separate Discord linking table is not required because the profile itself stores the one active primary Discord ID.
The customer buys using a billing email. Chargebee creates the billing customer and subscription.
The Chargebee customer and its billing email stay in the existing Chargebee customer and subscription tables.
Because the product is delivered through Discord, the customer confirms their Discord identity after purchase.
If that Discord ID already has a Customer Identity Profile, reuse it. If not, create one and link the current customer/subscription records.
The resolved profile groups the active entitlement used to assign the correct Discord access automatically.
One Customer Identity Profile can link multiple Chargebee customer records, their billing emails, and multiple subscriptions, but it should only have one primary Discord ID. The billing email belongs to the Chargebee customer record; it is not a separate standalone email profile. This keeps Discord access clean while preventing Chargebee customer records from becoming the account root.
Current Discord-linked users, Chargebee customers and their billing emails, subscriptions, lifetime purchases, and Discord-role access should be reviewed in a dry-run report first, then migrated into Customer Identity Profiles before the new resolver becomes the main path.
Automatic linking should only happen when the evidence is clear. Unclear ownership should pause the flow instead of merging accounts incorrectly.
Customer.io identity should not be changed immediately. The safer first step is to add profile attributes while keeping the current email or Chargebee-based identifiers stable.
One active primary Discord ID is still the right access model, but account recovery needs a controlled path when a customer loses or changes Discord accounts.
| Table | Current role | Implementation change | Why it matters |
|---|---|---|---|
|
Customer Identity Profiles New Required |
One root record per real customer/account. This is not a Chargebee customer record. |
profile_id, primary_discord_id, primary_discord_username, preferred_billing_email, profile_status, needs_review_reason, created_at, last_linked_at Linked records: Chargebee customers, subscriptions, and optional Discord access records. |
This gives staff and automation one stable account record while still allowing multiple Chargebee customer records, their billing emails, and multiple subscriptions to belong to the same customer. The primary_discord_id on this table becomes the source of truth for Discord identity. |
|
Chargebee Customers Core Required |
Stores each Chargebee customer, its billing email, name fields, and the current customer-level Discord link used today. | Customer Identity Profile Linked record field; expose profile_id as a lookup/search field. Keep discord_id as a compatibility/reference field during migration. |
Multiple Chargebee customer rows can link to the same Customer Identity Profile, which solves the different Chargebee account or billing-email problem without treating a billing record or customer-level discord_id as the root account. |
|
Chargebee Subscriptions Core Required |
Stores subscription, lifetime purchase, plan, Chargebee status, renewal status, Discord role, and entitlement fields. | Customer Identity Profile Linked record field; expose profile_id as a lookup/search field. Keep active_discord_id as a compatibility/reference field during migration. |
Upgrade, cancellation, and role-removal checks can look across every subscription linked to the same profile instead of only one Chargebee customer_id. |
|
Discord Role Members Operational Scope-based |
Tracks Discord users, linked Discord IDs, active role state, and any Discord-native access state. | Customer Identity Profile Optional linked record field; add it when Discord-native subscribers or role-state recovery need to be handled through the profile model. |
This is not required as the root identity layer. Its value is connecting Discord role state to the same profile used for Chargebee access, so Discord-native access can be checked before roles are assigned or removed. |
Create the profile root, backfill the key existing records, and update the resolver used by login, linking, upgrades, cancellations, and role handling. Other tables can receive profile fields later only if a clear operational need appears.
Add a Customer Identity Profiles table config value, a Customer Identity Profile record type, and Airtable helpers to find or create profiles, attach Chargebee records, and resolve profile-wide access.
Store the active Discord account on Customer Identity Profiles.primary_discord_id, enforce one active primary Discord ID per profile, and keep existing Chargebee customer and subscription Discord fields as compatibility fields during migration.
The current customer table represents Chargebee customers. If the same person purchases with two billing emails, Chargebee can create two customer records, so the profile table needs to sit above Chargebee and link those records together.
| Current flow | What stays the same | Profile adjustment |
|---|---|---|
| Checkout and purchase | Customers still buy with a billing email and Chargebee still creates the billing customer, invoice, and subscription. | The Chargebee customer, its billing email, customer ID, and subscription are matched to an existing Customer Identity Profile when possible. If no verified Discord-backed profile exists yet, Discord linking is required before full portal and product access. |
| Discord OAuth linking | Discord remains the preferred product login and the main identity used for access to the Discord-based product. | The Discord ID is checked first as the strongest match. If it already belongs to a Customer Identity Profile, new Chargebee customers and their billing emails link to that same profile. |
| Portal login | Customers can still use Discord or email. Email remains useful for login, billing lookup, recovery, and Chargebee purchase history. | The portal resolves the profile from Discord ID, the billing email on a Chargebee customer, or Chargebee customer ID. Email-only access can find billing context, but verified Discord is required for full dashboard and product access. |
| Chargebee webhooks | Subscription created, cancelled, renewed, upgraded, and lifetime purchase events still come from Chargebee. | Webhook handling writes or resolves the linked profile instead of treating each Chargebee customer or billing email as an isolated account. Entitlement checks use all records linked to the profile. |
| Discord role handling | The existing role assignment and removal automation remains the access mechanism. | Before roles are removed, the system checks all linked monthly, yearly, lifetime, and valid Discord-based entitlements on the profile. Access remains if any valid entitlement still exists. |
| Customer.io sync | Customer.io identity should not be changed immediately because that can affect messaging history and automations. | Add profile_id and profile summary attributes first. After profile_id is stable, messaging segments can gradually use the grouped data. |
| Airtable and staff support | Airtable can remain the operational view for customers, subscriptions, access, and support checks. | Add the Customer Identity Profiles table, then link the key customer, subscription, and Discord access records to it. Current records are backfilled, while conflicting records are sent to review. |
The customer buys using a billing email. Chargebee creates the billing customer and subscription.
The system checks whether the Chargebee customer, its billing email, or known subscription already links to a Customer Identity Profile.
If the resolved profile does not have verified Discord, the customer must link Discord before full dashboard and product access.
The Chargebee customer, its billing email, and subscription link to the resolved Discord-backed profile.
The grouped records now have the billing identity, Discord identity, and active entitlement needed for access.
Discord is preferred. Email remains available for billing lookup and recovery.
The system finds the Customer Identity Profile from Discord ID first, then email or Chargebee customer when needed.
If the profile does not have verified Discord yet, the customer completes Discord linking before full access.
The dashboard can show one account view by loading records linked to the same profile.
The release is working when a customer with two Chargebee customer records or billing emails and the same Discord ID resolves to one Customer Identity Profile and one profile_id, role removal checks every active monthly, yearly, lifetime, and valid Discord-based entitlement linked to that profile, conflicting ownership goes to review, and Customer.io receives profile_id attributes without changing existing identities.
Create the Customer Identity Profiles table, then backfill current Discord-linked users, Chargebee customers, subscriptions, and Discord access records while existing flows continue running.
Update portal login, Discord linking, and entitlement checks so access is based on all records linked to the same profile instead of one isolated customer record.
Once profile links are stable, improve the Airtable views and add richer support or engagement workflows on top of the Customer Identity Profiles table.
This approach solves the account fragmentation problem with the fewest schema changes: keep the current tables, add one Customer Identity Profiles table, link existing records to it, and update the resolver and entitlement checks around that profile.