> ## Documentation Index
> Fetch the complete documentation index at: https://stytch.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Reconciling data models

> Map your existing user model to Stytch's authentication data model.

export const jit_provisioning = "Just-in-time provisioning: allow new Members to be added to an Organization as soon as they authenticate, based on email domain or SSO connection.";

export const organization = "Represents an instance or tenant in your application, typically mapping to each of your top-level customers.";

export const member = "Represents an individual end user's account within a given Organization, uniquely identified within that Organization by their email address.";

export const userTip = "Represents an end user's account in your application.";

<Tabs>
  <Tab title="Consumer auth">
    Before migrating, align your existing data model to Stytch's Consumer <Tooltip tip={userTip}>User</Tooltip> object. This will help you plan which identifiers, auth factors, and metadata to migrate and how to map your internal IDs.

    ## Key data to map

    * **Unique identifiers**: Decide whether email, phone, or both will identify users, and verify uniqueness.
    * **Auth factors**: Inventory which factors each user has (passwords, email, phone, passkeys, etc.).
    * **Metadata**: Identify which attributes should move into `trusted_metadata` or `untrusted_metadata`.
    * **External IDs**: Preserve your internal user ID by mapping it to Stytch's `external_id`.
    * **Session data**: Plan how you'll validate sessions post-migration and whether you'll use Session Tokens or JWTs.
    * **Redirects and domains**: Ensure redirect URLs and authorized domains are configured in the Dashboard.

    ## Recommended mapping approach

    1. Start with the [Consumer data model](/consumer-auth/data-model) to understand the Stytch User object.
    2. Map your internal user identifier to [External IDs](/resources/migrations/external-ids#consumer-auth).
    3. Decide which user attributes are authoritative in your system versus Stytch, then align metadata accordingly.
    4. Plan for changes in auth factors (for example, if you're adding magic links or passkeys post-migration).

    ## Questions to answer

    * Where is authentication handled today (frontend, backend, or both)?
    * Which auth methods do users rely on (passwords, email, phone, or multiple)?
    * How many factors does a user typically have?
    * Do you need to support a web app, mobile app, or both?

    For a broader migration checklist, see [Migration overview](/resources/migrations/overview#consumer-auth).
  </Tab>

  <Tab title="B2B auth">
    The first step of planning your migration to Stytch is planning out how you want to connect your current data model to Stytch's core entities. This guide outlines the key considerations and approaches for how to do this for a range of existing data models.

    ## Overview of Stytch's data model

    Stytch's [B2B data model](/multi-tenant-auth/data-model) is centered around two first-class API entities: <Tooltip tip={organization}>Organizations</Tooltip> and <Tooltip tip={member}>Members</Tooltip>.

    1. A Stytch [Organization](/api-reference/b2b/api/organizations/overview) is the top-level “tenant", which groups one or more [Members](/api-reference/b2b/api/members/overview) together within your application.
    2. A Stytch [Member](/api-reference/b2b/api/members/overview) is an end user who belongs to an Organization. Stytch uses **email address** as the primary unique identifier for Members within an Organization. An end user can belong to multiple Organizations by having multiple Member records, which are linked together by using the same email address.

    For more details and technical specifics on Organizations and Members, visit our [B2B Overview](/multi-tenant-auth/overview) or the [API reference](/api-reference/b2b/api/overview).

    ## Defining the top-level tenant

    The top-level tenant of your application usually maps to your business customers, who pay for your service and own all the data and resources within their instance. Key characteristics of a top-level tenant are:

    * **Account Ownership:** the tenant holds the subscription or contract for using your services, or has the ability to manage billing and upgrade if you have a free tier
    * **Access Management:** the tenant determines which end users can access their instance, and what roles and permissions authorized end users can do within the context of the tenant
    * **User Management:** the tenant can manage end users, performing admin actions like updating emails or resetting MFA enrollment
    * **Data Segregation:** the data and configurations that belong to the tenant are *typically* isolated from other tenants, ensuring strong governance and security

    The top-level tenant you've identified will map to Stytch's **Organization** concept.

    <Tip>If you have a mix of business customers and individual end users, we recommend creating an Organization behind the scenes for each individual user "tenant" in order to allow these single-player accounts to seamlessly upgrade and add collaborators in the future. This is the same approach that Notion takes, creating a WorkspaceID in the background for both single-player and multi-player sign-ups.</Tip>

    To create a clean 1:1 mapping between your internal representation of the top-level tenant and Stytch's Organization, store the stable Stytch `organization_id` as a column on your equivalent entity.

    Outside of the UUID, Stytch Organizations can also be uniquely identified by `organization_slug`, which is the unique URL identifier of your application (e.g. `acme` for `acme.your-app.com` or `your-app.com/team/acme`). However, as the organization slug can be updated, we recommend primarily using the `organization_id` in any internal references to the Stytch object.

    If you have internal information about the Organization that you want to have accessible in Stytch (for example, to automatically include in the [JWT Custom Claims](https://stytch.com/dashboard/custom-claim-templates) for Member Sessions), you can use the `trusted_metadata` field on the Organization.

    Stytch supports a wide range of **authentication and provisioning settings** that you can offload entirely to Stytch, to control approved authentication methods, MFA Policies, <Tooltip tip={jit_provisioning}>Just-in-Time (JIT) Provisioning</Tooltip> and more. Refer to the [Organization object](/api-reference/b2b/api/organizations/organization-object) in the API reference to see all available fields and settings. You can set these while migrating Organizations in via the CreateOrganization method.

    ```js theme={null}
    [
      {
        "organization_id": "organization-test-07971b...",
        "organization_name": "Team A",
        "organization_slug": "team-a",
        "trusted_metadata": {
          "billing_tier": "free",
          "privacy_setting": "public"
        },
        "email_invites": "ALL_ALLOWED",
        "email_jit_provisioning": "NOT_ALLOWED",
        ...
      },
      {
        "organization_id": "organization-test-02645e...",
        "organization_name": "Team B",
        "organization_slug": "team-b",
        "trusted_metadata": {
          "billing_tier": "premium",
          "privacy_setting": "private"
        },
      	"email_invites": "RESTRICTED",
        "email_jit_provisioning": "RESTRICTED",
        "email_allowed_domains": ["stytch.com"],
        ...
      },
      {
        "organization_id": "organization-test-09320h...",
        "organization_name": "Team C",
        "organization_slug": "team-c",
        "trusted_metadata": {
          "billing_tier": "enterprise",
          "privacy_setting": "private"
        },
        "auth_methods": "RESTRICTED",
        "allowed_auth_methods": ["sso"],
        ...
      }
    ]
    ```

    ## Defining & mapping end users

    Stytch's user entity is the **Member** object, which is scoped to a *specific* Organization and is uniquely identified *within* that Organization by their email address. If `claude.shannon@stytch.com` belongs to three different Organizations, there will be three entirely distinct Member records associated with `claude.shannon@stytch.com`.

    End users can still "switch" between different Organizations without having to log out and log back in, but this data model ensures the **data isolation** expected by enterprise companies, and allows each Organization to have **complete control** over the end users who are accessing their application.

    Depending on how your application enforces and stores the relationships between users and groups, you will need to create one or many Stytch Member objects for every application user.

    ### Migrating from 1:1 data model

    If your application already defines an end user as belonging to a single Organization, you will create one Member record for each existing user record in your system. Store the stable Stytch `member_id` on your internal representation of the user for easy queries.

    For applications where the 1:1 data model is global, and an end user can *only* belong to one Organization at a time, keep in mind that Stytch does not have this restriction and is more of a "many 1:1 model". If your application relies on the assumption that a single email will only ever be associated with a single Organization, you will need to add in your own enforcement of this constraint before calling Stytch.

    While we do recommend removing this restriction, as it can cause unnecessary friction for contractors or companies with multiple instances of your application, it is not necessary to do as part of your migration.

    ### Migrating from 1:many data model

    If your application allows a single User record to be *shared* across multiple Organizations, that all reference the same UserID, you will create multiple Member objects for each User in your system -- one for each Organization that the end user is shared across.

    If you already have a membership table storing the relationship between User\<>Organizations, you can add the Stytch `member_ids` to that record. However, keep in mind that in Stytch changing the email or name of one Member object will not impact the other Member records that share the original email and so it is important to keep this table in sync and/or ensure that all AuthN/AuthZ functionality looks to Stytch as the source of truth rather than this table.

    A fairly common approach with customer is to migrate to Stytch with their existing data model in place leveraging a mapping table like the one described above, and then later on update their internal data model to be more consistent with an organization-tenancy model, improving the security and data governance controls for their enterprise customers.

    Regardless of either scenario, you can leverage the following features to enrich the Stytch Member object:

    * **Custom metadata**: Utilize the custom `trusted_metadata` and `untrusted_metadata` fields on the Member object to store any application or business-specific attributes for your end user and their membership.
    * **Authentication and authorization settings**: Configure a Member's auth settings to control MFA enrollment, breakglass privileges, and roles and permissions.

    Refer to the [Member object](/api-reference/b2b/api/members/member-object) in the API reference to see all available fields and settings.

    ```js theme={null}
    [
      // These three Member objects are all the same end user
      {
        "member_id": "member-test-32fc...",
        "organization_id": "organization-test-07971...",
        "email_address": "adalovelace@stytch.com",
        "email_address_verified": true,
        "name": "Ada Lovelace",
        "status": "active",
        "untrusted_metadata": {
          "job_title": "Engineer",
          "preferred_locales": ["en", "es"]
        }
      },
      {
        "member_id": "member-test-83ei...",
        "organization_id": "organization-test-08264...",
        "email_address": "adalovelace@stytch.com",
        "email_address_verified": true,
        "name": "Miss Ada",
        "status": "active",
        "untrusted_metadata": {
          "timezone": "EST"
        }
      },
      {
        "member_id": "member-test-65yu...",
        "organization_id": "organization-test-02598...",
        "email_address": "adalovelace@stytch.com",
        "email_address_verified": true,
        "name": "Ada",
        "status": "active",
        "untrusted_metadata": {
          "display_theme": "dark"
        }
      }
    ]
    ```

    ## Other considerations

    ### Account deduplication

    Stytch utilizes the email address as a unique primary key for identifying Members within an Organization. This means two things:

    1. Two different Members cannot use the same email address within a single Organization.
    2. Stytch will automatically consolidate Members who log into an Organization using the same email address with different auth methods. For example, an end user authenticates into Organization A using Email Magic Links and the email address `example@stytch.com`. Later, they authenticate into Organization A again with the same email address but this time using Google OAuth. Rather than create duplicate Member records, Stytch consolidates both auth instances under one Member object and `member_id`.

    For this reason, you may need to merge your users' accounts before migrating to Stytch. If your script attempts to manually create two Members in an Organization in Stytch with the same email address, you will receive a `duplicate_email` error.

    ### Passwords

    Stytch offers two different approaches to password authentication:

    1. **Cross-organization passwords:** allows end users to use the same password across all Organizations they belong to under that email. This approach is best if you are migrating from a 1:many user to Organization data model, as it will allow a seamless transition to Stytch's organization-first approach without any impact to UX
    2. **Organization-scoped passwords:** scopes the password to each individual Member object within a single Organization. This approach is best if your customers are highly security conscious, and want strong multi-tenant separation so that a password reset in another Organization does not impact their Member's authentication options

    You can select which approach you want to use for your project in the Stytch Dashboard [Passwords Policy](https://stytch.com/dashboard/password-strength-config) page.
    Please note that **you cannot switch password approaches if there are existing passwords in your project**, so make sure to update the setting to your desired approach prior to kicking off your migration to Stytch.

    ### Linking Stytch Members and Organizations back to your db

    You should continue to maintain your own internal user and groups tables in your application, and link Stytch’s `member_id`s and `organization_id`s in your schema. You can also add your internal identifier references as a `trusted_metadata` field on the Stytch Member and the Stytch Organization record using metadata.

    ## What's next

    With an understanding of how your user and organization data model will map to that of Stytch, see our guide to [migrate users and organizations to Stytch](/resources/migrations/migrating-user-data#b2b-auth).
  </Tab>
</Tabs>
