{
    "componentChunkName": "component---src-pages-blog-markdown-remark-fields-slug-js",
    "path": "/blog/clerk-migration",
    "result": {"data":{"markdownRemark":{"html":"<p>Migrating authentication systems represents a critical infrastructure decision that affects every user interaction with your application.\nClerk provides a robust authentication platform, but developers increasingly seek alternatives offering greater control, cost predictability, or self-hosting capabilities. SuperTokens delivers these advantages while maintaining enterprise-grade security and a\ncomprehensive feature set.</p>\n<p>This guide provides a detailed roadmap for migrating from Clerk to SuperTokens, covering migration strategies, user data export and import procedures, session handling, multi-factor authentication (MFA) preservation, and rollout best practices.</p>\n<h2 id=\"migration-strategies-choosing-your-approach\" style=\"position:relative;\"><a href=\"#migration-strategies-choosing-your-approach\" aria-label=\"migration strategies choosing your approach permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a><strong>Migration Strategies: Choosing Your Approach</strong></h2>\n<p>The selection of a migration strategy depends on the size of the user base, the acceptable downtime, and operational constraints. <a href=\"https://supertokens.com/\" target=\"_blank\" rel=\"nofollow\">SuperTokens</a> supports multiple migration patterns, each with distinct trade-offs.</p>\n<h3 id=\"what-migration-options-exist\" style=\"position:relative;\"><a href=\"#what-migration-options-exist\" aria-label=\"what migration options exist permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a><strong>What Migration Options Exist?</strong></h3>\n<ul>\n<li><strong>Lazy Migration (Trickle Migration)</strong></li>\n</ul>\n<p>Users migrate individually upon their next login attempt. The system checks the Clerk first, validates credentials, imports the user into SuperTokens, and issues a new session. This approach requires maintaining both systems temporarily, but it distributes the migration load over time and targets active users first.</p>\n<ul>\n<li><strong>Bulk Import</strong></li>\n</ul>\n<p>Export all users from Clerk and import them into SuperTokens in batches by using the <code class=\"language-text\">/bulk-import/users</code> API. This method migrates users upfront, enabling faster Clerk deprecation.</p>\n<ul>\n<li><strong>Full Export/Import via Scripts</strong></li>\n</ul>\n<p>Automated scripts extract users from Clerk, transform data into the SuperTokens format, and execute imports. This approach offers maximum control for complex migration requirements.</p>\n<ul>\n<li><strong>Hybrid Approach</strong></li>\n</ul>\n<p>Combine bulk import for the majority of users with lazy migration for edge cases or recently registered accounts.</p>\n<h3 id=\"1-trickle-migration-lazy-migration\" style=\"position:relative;\"><a href=\"#1-trickle-migration-lazy-migration\" aria-label=\"1 trickle migration lazy migration permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a><strong>1. Trickle Migration (Lazy Migration)</strong></h3>\n<p>Trickle migration enables seamless, incremental user transitions without bulk data operations. This approach mirrors Clerk’s own migration recommendations for minimal disruption.</p>\n<p><strong>How It Works:</strong></p>\n<ol>\n<li>User attempts to log in with email and password.</li>\n<li>Check if the user exists in SuperTokens.</li>\n<li>If not found, authenticate against Clerk.</li>\n<li>Upon successful Clerk authentication, import the user into SuperTokens.</li>\n<li>Issue SuperTokens session token.</li>\n<li>Subsequent logins authenticate directly against SuperTokens.</li>\n</ol>\n<p><strong>Advantages:</strong></p>\n<ul>\n<li>No downtime required</li>\n<li>Active users migrate first</li>\n<li>Minimal risk—each user migration is isolated</li>\n<li>Gradual load distribution</li>\n</ul>\n<p><strong>Considerations:</strong></p>\n<ul>\n<li>Requires maintaining both systems during transition</li>\n<li>Complete migration timeline depends on the user login frequency</li>\n<li>Inactive users may never migrate without eventual bulk import</li>\n</ul>\n<h3 id=\"2-bulk-import\" style=\"position:relative;\"><a href=\"#2-bulk-import\" aria-label=\"2 bulk import permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a><strong>2. Bulk Import</strong></h3>\n<p>Bulk import migrates all users upfront through SuperTokens’ <code class=\"language-text\">/bulk-import/users</code> endpoint, enabling rapid Clerk deprecation.</p>\n<p><strong>Key Steps:</strong></p>\n<ol>\n<li>Export the complete user dataset from the Clerk dashboard.</li>\n<li>Transform data into SuperTokens bulk import format.</li>\n<li>Submit batches (up to 10,000 users per request).</li>\n<li>Monitor import job status.</li>\n<li>Handle failures and retry as needed.</li>\n</ol>\n<p><strong>Advantages:</strong></p>\n<ul>\n<li>Fastest path to removing Clerk dependencies</li>\n<li>All users are available immediately</li>\n<li>Simpler post-migration architecture</li>\n<li>Predictable timeline</li>\n</ul>\n<p><strong>Considerations:</strong></p>\n<ul>\n<li>May require a maintenance window</li>\n<li>Higher initial load on infrastructure</li>\n<li>Failed imports require careful remediation</li>\n</ul>\n<h3 id=\"3-full-migration-via-scripts\" style=\"position:relative;\"><a href=\"#3-full-migration-via-scripts\" aria-label=\"3 full migration via scripts permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a><strong>3. Full Migration via Scripts</strong></h3>\n<p>Scripted migration provides maximum flexibility for complex requirements, inspired by Better Auth’s migration guides.</p>\n<p><strong>When to Use:</strong></p>\n<ul>\n<li>Large user bases require careful batch management</li>\n<li>Custom authentication flows or metadata schemas</li>\n<li>Need for detailed logging and audit trails</li>\n<li>Integration with existing DevOps pipelines</li>\n</ul>\n<p><strong>Script Responsibilities:</strong></p>\n<ul>\n<li>Export users from Clerk</li>\n<li>Transform data schemas (Clerk → SuperTokens format)</li>\n<li>Handle password hash compatibility</li>\n<li>Execute batch imports with retry logic</li>\n<li>Monitor progress and log failures</li>\n<li>Verify data integrity post-migration</li>\n</ul>\n<h2 id=\"exporting-and-importing-clerk-users\" style=\"position:relative;\"><a href=\"#exporting-and-importing-clerk-users\" aria-label=\"exporting and importing clerk users permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a><strong>Exporting and Importing Clerk Users</strong></h2>\n<p>Successful migration depends on accurately exporting Clerk user data and transforming it into a SuperTokens-compatible format.</p>\n<h3 id=\"export-users-from-clerk-dashboard\" style=\"position:relative;\"><a href=\"#export-users-from-clerk-dashboard\" aria-label=\"export users from clerk dashboard permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a><strong>Export Users from Clerk Dashboard</strong></h3>\n<p><strong>Steps:</strong></p>\n<ol>\n<li>Navigate to <strong><a href=\"https://clerk.com/user-authentication?utm_source=google&#x26;utm_medium=cpc&#x26;utm_campaign=%7Bcampaignname%7D&#x26;utm_adgroup=%7Badgroupname%7D&#x26;utm_term=clerk&#x26;gad_source=1&#x26;gad_campaignid=23228885670&#x26;gbraid=0AAAAAqJUiX7m311FiPI1I20vdkUmBaDeO&#x26;gclid=CjwKCAiAjojLBhAlEiwAcjhrDiP0PVXaecZ5o0nJRwjXDHnoC2VckT_z_i92YJMiQ4_PdGmy_7R0EBoCZZAQAvD_BwE\" target=\"_blank\" rel=\"nofollow\">Clerk Dashboard</a> → Configure section → settings</strong>.</li>\n<li>Click <strong>Export Users</strong>.</li>\n<li>Download an export file.</li>\n</ol>\n<p><span\n      class=\"gatsby-resp-image-wrapper\"\n      style=\"position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 630px; \"\n    >\n      <a\n    class=\"gatsby-resp-image-link\"\n    href=\"/static/2522a8b06a302bc6c79d04e7450e02c2/3d405/Dashboard.png\"\n    style=\"display: block\"\n    target=\"_blank\"\n    rel=\"noopener\"\n  >\n    <span\n    class=\"gatsby-resp-image-background-image\"\n    style=\"padding-bottom: 51.26582278481012%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAKCAYAAAC0VX7mAAAACXBIWXMAAAsTAAALEwEAmpwYAAACRUlEQVQoz12RXU8aURCGuTLWFlgEhN1zzu6eZfkSVJAW5UMJarFYpBqNoGi1qTVeGBvTNulP8Kb9y0/D2pimF09m5iTzzntmQjc3t7TbHbrdHba23tLpdOl0e+wPD9jd7dNstmm1N2m1nmi3N4O39fUmjUaLRqNNs7nBysoq9/dfCW1v9/B0jny+RDJpEo+nsCyHarWO7xexhIuU+hkhNablsJASpNMS3y+QyeSJRuMcHZ0Q6vcHFIpLVGt1TMtGSBchHGxbY1kK03xCWCqoLVPhWE6ArXQwtFyukEpJxuMJocHeEFdo8l4hiI5wg2ZPZ0inTOZjBpFIlNkXYWbnwqRiCfJJn2zCQ5o2lnBQSmMYCUajM0LH7w9pLNWpl2qUdZGyk8eWGkf7pGWGuJXDUh7bG2tUl0skU4IFU2IK+8n5/4L9dwMybpaCX0SZDkq4KFOStTVa+UiZx1MeO2sV1pcXsRJpXEuRUQ5iuqJ/BIMv7+3t47pZXO1jTncmbLLxBBXDYMmIosMvccNhzNk55NwrPMNAR6PoSBQ5dRq4tIlE5jk5OZ0KDoNLVSo1bNtDWnZQ1940qb1uUFhcIeMX0V4OV2dx3CkeSimksMnlypRKqwjhcXX1hVC3+5aZmTlisSSGkQysO3aGSqX+TLlcRf69/jRqZ4W818SIJqmvdRiPPtPtDri7+0Ho4eEbvV6f4fCQweADg/0DRuMzJpMLJpOPAWdnF1xcXAX5+fkl15c/ubv+xXB4zGRyze3Nd05PP/H4+Js/GHcxyCab9mcAAAAASUVORK5CYII='); background-size: cover; display: block;\"\n  ></span>\n  <img\n        class=\"gatsby-resp-image-image\"\n        alt=\"Dashboard\"\n        title=\"Dashboard\"\n        src=\"/static/2522a8b06a302bc6c79d04e7450e02c2/f058b/Dashboard.png\"\n        srcset=\"/static/2522a8b06a302bc6c79d04e7450e02c2/c26ae/Dashboard.png 158w,\n/static/2522a8b06a302bc6c79d04e7450e02c2/6bdcf/Dashboard.png 315w,\n/static/2522a8b06a302bc6c79d04e7450e02c2/f058b/Dashboard.png 630w,\n/static/2522a8b06a302bc6c79d04e7450e02c2/40601/Dashboard.png 945w,\n/static/2522a8b06a302bc6c79d04e7450e02c2/78612/Dashboard.png 1260w,\n/static/2522a8b06a302bc6c79d04e7450e02c2/3d405/Dashboard.png 1348w\"\n        sizes=\"(max-width: 630px) 100vw, 630px\"\n        style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;\"\n        loading=\"lazy\"\n        decoding=\"async\"\n      />\n  </a>\n    </span></p>\n<p><strong>Export Data Structure:</strong></p>\n<div\n              class=\"gatsby-code-button-container\"\n              data-toaster-id=\"25980338560973017000\"\n              data-toaster-class=\"gatsby-code-button-toaster\"\n              data-toaster-text-class=\"gatsby-code-button-toaster-text\"\n              data-toaster-text=\"Copied!\"\n              data-toaster-duration=\"3500\"\n              onClick=\"copyToClipboard(`{\n  &quot;id&quot;: &quot;user_2abc123&quot;,\n  &quot;email_addresses&quot;: [\n    {\n      &quot;email_address&quot;: &quot;user@example.com&quot;,\n      &quot;verification&quot;: { &quot;status&quot;: &quot;verified&quot; }\n    }\n  ],\n  &quot;password_hash&quot;: &quot;\\$2a\\$10\\$abcdefghijklmnopqrstuv&quot;,\n  &quot;password_hasher&quot;: &quot;bcrypt&quot;,\n  &quot;totp_secrets&quot;: [\n    {\n      &quot;secret&quot;: &quot;JBSWY3DPEHPK3PXP&quot;,\n      &quot;verified&quot;: true\n    }\n  ],\n  &quot;first_name&quot;: &quot;John&quot;,\n  &quot;last_name&quot;: &quot;Doe&quot;\n}`, `25980338560973017000`)\"\n            >\n              <div\n                class=\"gatsby-code-button\"\n                data-tooltip=\"\"\n              >\n                <svg class=\"gatsby-code-button-icon\" xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\"><path fill=\"none\" d=\"M0 0h24v24H0V0z\"/><path d=\"M16 1H2v16h2V3h12V1zm-1 4l6 6v12H6V5h9zm-1 7h5.5L14 6.5V12z\"/></svg>\n              </div>\n            </div>\n<div class=\"gatsby-highlight\" data-language=\"js\"><pre class=\"language-js\"><code class=\"language-js\"><span class=\"token punctuation\">{</span>\n  <span class=\"token string-property property\">\"id\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"user_2abc123\"</span><span class=\"token punctuation\">,</span>\n  <span class=\"token string-property property\">\"email_addresses\"</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">[</span>\n    <span class=\"token punctuation\">{</span>\n      <span class=\"token string-property property\">\"email_address\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"user@example.com\"</span><span class=\"token punctuation\">,</span>\n      <span class=\"token string-property property\">\"verification\"</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">{</span> <span class=\"token string-property property\">\"status\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"verified\"</span> <span class=\"token punctuation\">}</span>\n    <span class=\"token punctuation\">}</span>\n  <span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span>\n  <span class=\"token string-property property\">\"password_hash\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"$2a$10$abcdefghijklmnopqrstuv\"</span><span class=\"token punctuation\">,</span>\n  <span class=\"token string-property property\">\"password_hasher\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"bcrypt\"</span><span class=\"token punctuation\">,</span>\n  <span class=\"token string-property property\">\"totp_secrets\"</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">[</span>\n    <span class=\"token punctuation\">{</span>\n      <span class=\"token string-property property\">\"secret\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"JBSWY3DPEHPK3PXP\"</span><span class=\"token punctuation\">,</span>\n      <span class=\"token string-property property\">\"verified\"</span><span class=\"token operator\">:</span> <span class=\"token boolean\">true</span>\n    <span class=\"token punctuation\">}</span>\n  <span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span>\n  <span class=\"token string-property property\">\"first_name\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"John\"</span><span class=\"token punctuation\">,</span>\n  <span class=\"token string-property property\">\"last_name\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"Doe\"</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<h3 id=\"using-clerk-migration-scripts\" style=\"position:relative;\"><a href=\"#using-clerk-migration-scripts\" aria-label=\"using clerk migration scripts permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a><strong>Using Clerk Migration Scripts</strong></h3>\n<p>The SuperTokens community provides migration scripts that handle Clerk-specific data formats and common edge cases.</p>\n<p><strong>Supported Password Hash Algorithms:</strong></p>\n<ul>\n<li>bcrypt (most common)</li>\n<li>argon2id</li>\n<li>scrypt</li>\n<li>PBKDF2</li>\n<li>MD5 (legacy)</li>\n</ul>\n<p><strong>Script Features:</strong></p>\n<ul>\n<li>Automatic rate limit handling with exponential backoff</li>\n<li>Foreign key mapping preservation (Clerk user ID → SuperTokens external user ID)</li>\n<li>Batch processing for large datasets</li>\n<li>Progress tracking and resumable imports</li>\n<li>Validation and error reporting</li>\n</ul>\n<h3 id=\"formatting-for-supertokens-bulk-import\" style=\"position:relative;\"><a href=\"#formatting-for-supertokens-bulk-import\" aria-label=\"formatting for supertokens bulk import permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a><strong>Formatting for SuperTokens Bulk Import</strong></h3>\n<p>SuperTokens bulk import API requires a specific JSON structure with the following required fields:</p>\n<ul>\n<li><code class=\"language-text\">externalUserId</code>: Unique identifier (use Clerk’s user ID).</li>\n<li><code class=\"language-text\">loginMethods</code>: Array of authentication methods.</li>\n<li><code class=\"language-text\">totpDevices</code>: Array of MFA TOTP devices (optional).</li>\n<li><code class=\"language-text\">userMetadata</code>: Custom user data (optional).</li>\n</ul>\n<p><strong>Import Format:</strong></p>\n<div\n              class=\"gatsby-code-button-container\"\n              data-toaster-id=\"11524084368030250000\"\n              data-toaster-class=\"gatsby-code-button-toaster\"\n              data-toaster-text-class=\"gatsby-code-button-toaster-text\"\n              data-toaster-text=\"Copied!\"\n              data-toaster-duration=\"3500\"\n              onClick=\"copyToClipboard(`{\n  &quot;users&quot;: [\n    {\n      &quot;externalUserId&quot;: &quot;clerk_user_2abc123&quot;,\n      &quot;loginMethods&quot;: [\n        {\n          &quot;email&quot;: &quot;user@example.com&quot;,\n          &quot;passwordHash&quot;: &quot;\\$2a\\$10\\$abcdefghijklmnopqrstuv&quot;,\n          &quot;hashingAlgorithm&quot;: &quot;bcrypt&quot;,\n          &quot;verified&quot;: true\n        }\n      ],\n      &quot;totpDevices&quot;: [\n        {\n          &quot;secretKey&quot;: &quot;JBSWY3DPEHPK3PXP&quot;,\n          &quot;deviceName&quot;: &quot;Authenticator App&quot;\n        }\n      ],\n      &quot;userMetadata&quot;: {\n        &quot;firstName&quot;: &quot;John&quot;,\n        &quot;lastName&quot;: &quot;Doe&quot;\n      }\n    }\n  ]\n}`, `11524084368030250000`)\"\n            >\n              <div\n                class=\"gatsby-code-button\"\n                data-tooltip=\"\"\n              >\n                <svg class=\"gatsby-code-button-icon\" xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\"><path fill=\"none\" d=\"M0 0h24v24H0V0z\"/><path d=\"M16 1H2v16h2V3h12V1zm-1 4l6 6v12H6V5h9zm-1 7h5.5L14 6.5V12z\"/></svg>\n              </div>\n            </div>\n<div class=\"gatsby-highlight\" data-language=\"js\"><pre class=\"language-js\"><code class=\"language-js\"><span class=\"token punctuation\">{</span>\n  <span class=\"token string-property property\">\"users\"</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">[</span>\n    <span class=\"token punctuation\">{</span>\n      <span class=\"token string-property property\">\"externalUserId\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"clerk_user_2abc123\"</span><span class=\"token punctuation\">,</span>\n      <span class=\"token string-property property\">\"loginMethods\"</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">[</span>\n        <span class=\"token punctuation\">{</span>\n          <span class=\"token string-property property\">\"email\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"user@example.com\"</span><span class=\"token punctuation\">,</span>\n          <span class=\"token string-property property\">\"passwordHash\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"$2a$10$abcdefghijklmnopqrstuv\"</span><span class=\"token punctuation\">,</span>\n          <span class=\"token string-property property\">\"hashingAlgorithm\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"bcrypt\"</span><span class=\"token punctuation\">,</span>\n          <span class=\"token string-property property\">\"verified\"</span><span class=\"token operator\">:</span> <span class=\"token boolean\">true</span>\n        <span class=\"token punctuation\">}</span>\n      <span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span>\n      <span class=\"token string-property property\">\"totpDevices\"</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">[</span>\n        <span class=\"token punctuation\">{</span>\n          <span class=\"token string-property property\">\"secretKey\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"JBSWY3DPEHPK3PXP\"</span><span class=\"token punctuation\">,</span>\n          <span class=\"token string-property property\">\"deviceName\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"Authenticator App\"</span>\n        <span class=\"token punctuation\">}</span>\n      <span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span>\n      <span class=\"token string-property property\">\"userMetadata\"</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">{</span>\n        <span class=\"token string-property property\">\"firstName\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"John\"</span><span class=\"token punctuation\">,</span>\n        <span class=\"token string-property property\">\"lastName\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"Doe\"</span>\n      <span class=\"token punctuation\">}</span>\n    <span class=\"token punctuation\">}</span>\n  <span class=\"token punctuation\">]</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<p><strong>Field Mapping Reference:</strong></p>\n<table>\n<thead>\n<tr>\n<th>Clerk Field</th>\n<th>SuperTokens Field</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>id</td>\n<td>externalUserId</td>\n</tr>\n<tr>\n<td>email_addresses[0].email_address</td>\n<td>loginMethods[0].email</td>\n</tr>\n<tr>\n<td>password_hash</td>\n<td>loginMethods[0].passwordHash</td>\n</tr>\n<tr>\n<td>password_hasher</td>\n<td>loginMethods[0].hashingAlgorithm</td>\n</tr>\n<tr>\n<td>totp_secrets[0].secret</td>\n<td>totpDevices[0].secretKey</td>\n</tr>\n<tr>\n<td>first_name, last_name</td>\n<td>userMetadata.firstName, userMetadata.lastName</td>\n</tr>\n</tbody>\n</table>\n<h2 id=\"implementing-supertokens-after-clerk\" style=\"position:relative;\"><a href=\"#implementing-supertokens-after-clerk\" aria-label=\"implementing supertokens after clerk permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a><strong>Implementing SuperTokens After Clerk</strong></h2>\n<p>Successful migration requires proper SuperTokens setup and integration with existing application code.</p>\n<h3 id=\"core-setup\" style=\"position:relative;\"><a href=\"#core-setup\" aria-label=\"core setup permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a><strong>Core Setup</strong></h3>\n<p><strong>Install SuperTokens Core:</strong></p>\n<p>For self-hosted deployments:</p>\n<div\n              class=\"gatsby-code-button-container\"\n              data-toaster-id=\"16829591434960212000\"\n              data-toaster-class=\"gatsby-code-button-toaster\"\n              data-toaster-text-class=\"gatsby-code-button-toaster-text\"\n              data-toaster-text=\"Copied!\"\n              data-toaster-duration=\"3500\"\n              onClick=\"copyToClipboard(`docker run -d -p 3567:3567 registry.supertokens.io/supertokens/supertokens-postgresql`, `16829591434960212000`)\"\n            >\n              <div\n                class=\"gatsby-code-button\"\n                data-tooltip=\"\"\n              >\n                <svg class=\"gatsby-code-button-icon\" xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\"><path fill=\"none\" d=\"M0 0h24v24H0V0z\"/><path d=\"M16 1H2v16h2V3h12V1zm-1 4l6 6v12H6V5h9zm-1 7h5.5L14 6.5V12z\"/></svg>\n              </div>\n            </div>\n<div class=\"gatsby-highlight\" data-language=\"js\"><pre class=\"language-js\"><code class=\"language-js\">docker run <span class=\"token operator\">-</span>d <span class=\"token operator\">-</span>p <span class=\"token number\">3567</span><span class=\"token operator\">:</span><span class=\"token number\">3567</span> registry<span class=\"token punctuation\">.</span>supertokens<span class=\"token punctuation\">.</span>io<span class=\"token operator\">/</span>supertokens<span class=\"token operator\">/</span>supertokens<span class=\"token operator\">-</span>postgresql</code></pre></div>\n<p>For managed hosting, use SuperTokens Cloud and obtain the connection URI from the dashboard.</p>\n<p><strong>Install SDKs:</strong></p>\n<div\n              class=\"gatsby-code-button-container\"\n              data-toaster-id=\"18582452509000614000\"\n              data-toaster-class=\"gatsby-code-button-toaster\"\n              data-toaster-text-class=\"gatsby-code-button-toaster-text\"\n              data-toaster-text=\"Copied!\"\n              data-toaster-duration=\"3500\"\n              onClick=\"copyToClipboard(`# Backend\nnpm install supertokens-node\n\n# Frontend (React)\nnpm install supertokens-auth-react`, `18582452509000614000`)\"\n            >\n              <div\n                class=\"gatsby-code-button\"\n                data-tooltip=\"\"\n              >\n                <svg class=\"gatsby-code-button-icon\" xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\"><path fill=\"none\" d=\"M0 0h24v24H0V0z\"/><path d=\"M16 1H2v16h2V3h12V1zm-1 4l6 6v12H6V5h9zm-1 7h5.5L14 6.5V12z\"/></svg>\n              </div>\n            </div>\n<div class=\"gatsby-highlight\" data-language=\"js\"><pre class=\"language-js\"><code class=\"language-js\"># Backend\nnpm install supertokens<span class=\"token operator\">-</span>node\n\n# <span class=\"token function\">Frontend</span> <span class=\"token punctuation\">(</span>React<span class=\"token punctuation\">)</span>\nnpm install supertokens<span class=\"token operator\">-</span>auth<span class=\"token operator\">-</span>react</code></pre></div>\n<p><strong>Backend Configuration:</strong></p>\n<div\n              class=\"gatsby-code-button-container\"\n              data-toaster-id=\"60257895233710920000\"\n              data-toaster-class=\"gatsby-code-button-toaster\"\n              data-toaster-text-class=\"gatsby-code-button-toaster-text\"\n              data-toaster-text=\"Copied!\"\n              data-toaster-duration=\"3500\"\n              onClick=\"copyToClipboard(`import SuperTokens from &quot;supertokens-node&quot;;\nimport EmailPassword from &quot;supertokens-node/recipe/emailpassword&quot;;\nimport Session from &quot;supertokens-node/recipe/session&quot;;\n\n\nSuperTokens.init({\n  framework: &quot;express&quot;,\n  supertokens: {\n    connectionURI: &quot;http://localhost:3567&quot;,\n  },\n  appInfo: {\n    appName: &quot;Your App&quot;,\n    apiDomain: &quot;http://localhost:3001&quot;,\n    websiteDomain: &quot;http://localhost:3000&quot;,\n    apiBasePath: &quot;/auth&quot;,\n    websiteBasePath: &quot;/auth&quot;,\n  },\n  recipeList: [\n    EmailPassword.init(),\n    Session.init(),\n  ],\n});`, `60257895233710920000`)\"\n            >\n              <div\n                class=\"gatsby-code-button\"\n                data-tooltip=\"\"\n              >\n                <svg class=\"gatsby-code-button-icon\" xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\"><path fill=\"none\" d=\"M0 0h24v24H0V0z\"/><path d=\"M16 1H2v16h2V3h12V1zm-1 4l6 6v12H6V5h9zm-1 7h5.5L14 6.5V12z\"/></svg>\n              </div>\n            </div>\n<div class=\"gatsby-highlight\" data-language=\"js\"><pre class=\"language-js\"><code class=\"language-js\"><span class=\"token keyword\">import</span> SuperTokens <span class=\"token keyword\">from</span> <span class=\"token string\">\"supertokens-node\"</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">import</span> EmailPassword <span class=\"token keyword\">from</span> <span class=\"token string\">\"supertokens-node/recipe/emailpassword\"</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">import</span> Session <span class=\"token keyword\">from</span> <span class=\"token string\">\"supertokens-node/recipe/session\"</span><span class=\"token punctuation\">;</span>\n\n\nSuperTokens<span class=\"token punctuation\">.</span><span class=\"token function\">init</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">{</span>\n  <span class=\"token literal-property property\">framework</span><span class=\"token operator\">:</span> <span class=\"token string\">\"express\"</span><span class=\"token punctuation\">,</span>\n  <span class=\"token literal-property property\">supertokens</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token literal-property property\">connectionURI</span><span class=\"token operator\">:</span> <span class=\"token string\">\"http://localhost:3567\"</span><span class=\"token punctuation\">,</span>\n  <span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span>\n  <span class=\"token literal-property property\">appInfo</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token literal-property property\">appName</span><span class=\"token operator\">:</span> <span class=\"token string\">\"Your App\"</span><span class=\"token punctuation\">,</span>\n    <span class=\"token literal-property property\">apiDomain</span><span class=\"token operator\">:</span> <span class=\"token string\">\"http://localhost:3001\"</span><span class=\"token punctuation\">,</span>\n    <span class=\"token literal-property property\">websiteDomain</span><span class=\"token operator\">:</span> <span class=\"token string\">\"http://localhost:3000\"</span><span class=\"token punctuation\">,</span>\n    <span class=\"token literal-property property\">apiBasePath</span><span class=\"token operator\">:</span> <span class=\"token string\">\"/auth\"</span><span class=\"token punctuation\">,</span>\n    <span class=\"token literal-property property\">websiteBasePath</span><span class=\"token operator\">:</span> <span class=\"token string\">\"/auth\"</span><span class=\"token punctuation\">,</span>\n  <span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span>\n  <span class=\"token literal-property property\">recipeList</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">[</span>\n    EmailPassword<span class=\"token punctuation\">.</span><span class=\"token function\">init</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n    Session<span class=\"token punctuation\">.</span><span class=\"token function\">init</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n  <span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span>\n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></code></pre></div>\n<p><strong>Frontend Configuration:</strong></p>\n<div\n              class=\"gatsby-code-button-container\"\n              data-toaster-id=\"94890204408837980000\"\n              data-toaster-class=\"gatsby-code-button-toaster\"\n              data-toaster-text-class=\"gatsby-code-button-toaster-text\"\n              data-toaster-text=\"Copied!\"\n              data-toaster-duration=\"3500\"\n              onClick=\"copyToClipboard(`import SuperTokens from &quot;supertokens-auth-react&quot;;\nimport EmailPassword from &quot;supertokens-auth-react/recipe/emailpassword&quot;;\nimport Session from &quot;supertokens-auth-react/recipe/session&quot;;\n\n\nSuperTokens.init({\n  appInfo: {\n    appName: &quot;Your App&quot;,\n    apiDomain: &quot;http://localhost:3001&quot;,\n    websiteDomain: &quot;http://localhost:3000&quot;,\n    apiBasePath: &quot;/auth&quot;,\n    websiteBasePath: &quot;/auth&quot;,\n  },\n  recipeList: [\n    EmailPassword.init(),\n    Session.init(),\n  ],\n});`, `94890204408837980000`)\"\n            >\n              <div\n                class=\"gatsby-code-button\"\n                data-tooltip=\"\"\n              >\n                <svg class=\"gatsby-code-button-icon\" xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\"><path fill=\"none\" d=\"M0 0h24v24H0V0z\"/><path d=\"M16 1H2v16h2V3h12V1zm-1 4l6 6v12H6V5h9zm-1 7h5.5L14 6.5V12z\"/></svg>\n              </div>\n            </div>\n<div class=\"gatsby-highlight\" data-language=\"js\"><pre class=\"language-js\"><code class=\"language-js\"><span class=\"token keyword\">import</span> SuperTokens <span class=\"token keyword\">from</span> <span class=\"token string\">\"supertokens-auth-react\"</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">import</span> EmailPassword <span class=\"token keyword\">from</span> <span class=\"token string\">\"supertokens-auth-react/recipe/emailpassword\"</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">import</span> Session <span class=\"token keyword\">from</span> <span class=\"token string\">\"supertokens-auth-react/recipe/session\"</span><span class=\"token punctuation\">;</span>\n\n\nSuperTokens<span class=\"token punctuation\">.</span><span class=\"token function\">init</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">{</span>\n  <span class=\"token literal-property property\">appInfo</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token literal-property property\">appName</span><span class=\"token operator\">:</span> <span class=\"token string\">\"Your App\"</span><span class=\"token punctuation\">,</span>\n    <span class=\"token literal-property property\">apiDomain</span><span class=\"token operator\">:</span> <span class=\"token string\">\"http://localhost:3001\"</span><span class=\"token punctuation\">,</span>\n    <span class=\"token literal-property property\">websiteDomain</span><span class=\"token operator\">:</span> <span class=\"token string\">\"http://localhost:3000\"</span><span class=\"token punctuation\">,</span>\n    <span class=\"token literal-property property\">apiBasePath</span><span class=\"token operator\">:</span> <span class=\"token string\">\"/auth\"</span><span class=\"token punctuation\">,</span>\n    <span class=\"token literal-property property\">websiteBasePath</span><span class=\"token operator\">:</span> <span class=\"token string\">\"/auth\"</span><span class=\"token punctuation\">,</span>\n  <span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span>\n  <span class=\"token literal-property property\">recipeList</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">[</span>\n    EmailPassword<span class=\"token punctuation\">.</span><span class=\"token function\">init</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n    Session<span class=\"token punctuation\">.</span><span class=\"token function\">init</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n  <span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span>\n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></code></pre></div>\n<h3 id=\"lazytrickle-migration-integration\" style=\"position:relative;\"><a href=\"#lazytrickle-migration-integration\" aria-label=\"lazytrickle migration integration permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a><strong>Lazy/Trickle Migration Integration</strong></h3>\n<p>Integrate lazy migration logic into your authentication flow:</p>\n<div\n              class=\"gatsby-code-button-container\"\n              data-toaster-id=\"42313099139533820000\"\n              data-toaster-class=\"gatsby-code-button-toaster\"\n              data-toaster-text-class=\"gatsby-code-button-toaster-text\"\n              data-toaster-text=\"Copied!\"\n              data-toaster-duration=\"3500\"\n              onClick=\"copyToClipboard(`app.post(&quot;/auth/signin&quot;, async (req, res) => {\n  const { email, password } = req.body;\n \n  // Check SuperTokens first\n  let user = await EmailPassword.getUserByEmail(email);\n \n  if (!user) {\n    // User not migrated - check Clerk\n    const clerkUser = await clerk.users.getUser({ emailAddress: [email] });\n   \n    if (clerkUser && await clerk.verifyPassword(clerkUser.id, password)) {\n      // Import to SuperTokens\n      await fetch(&quot;http://localhost:3567/bulk-import/users&quot;, {\n        method: &quot;POST&quot;,\n        body: JSON.stringify({\n          users: [{\n            externalUserId: clerkUser.id,\n            loginMethods: [{\n              email: clerkUser.emailAddresses[0].emailAddress,\n              passwordHash: clerkUser.passwordDigest,\n              hashingAlgorithm: &quot;bcrypt&quot;,\n            }],\n          }],\n        }),\n      });\n     \n      user = await EmailPassword.getUserByEmail(email);\n    }\n  }\n \n  // Create SuperTokens session\n  if (user) {\n    await Session.createNewSession(req, res, user.id);\n    res.json({ status: &quot;OK&quot; });\n  } else {\n    res.status(401).json({ error: &quot;Invalid credentials&quot; });\n  }\n});`, `42313099139533820000`)\"\n            >\n              <div\n                class=\"gatsby-code-button\"\n                data-tooltip=\"\"\n              >\n                <svg class=\"gatsby-code-button-icon\" xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\"><path fill=\"none\" d=\"M0 0h24v24H0V0z\"/><path d=\"M16 1H2v16h2V3h12V1zm-1 4l6 6v12H6V5h9zm-1 7h5.5L14 6.5V12z\"/></svg>\n              </div>\n            </div>\n<div class=\"gatsby-highlight\" data-language=\"js\"><pre class=\"language-js\"><code class=\"language-js\">app<span class=\"token punctuation\">.</span><span class=\"token function\">post</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"/auth/signin\"</span><span class=\"token punctuation\">,</span> <span class=\"token keyword\">async</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\">req<span class=\"token punctuation\">,</span> res</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n  <span class=\"token keyword\">const</span> <span class=\"token punctuation\">{</span> email<span class=\"token punctuation\">,</span> password <span class=\"token punctuation\">}</span> <span class=\"token operator\">=</span> req<span class=\"token punctuation\">.</span>body<span class=\"token punctuation\">;</span>\n \n  <span class=\"token comment\">// Check SuperTokens first</span>\n  <span class=\"token keyword\">let</span> user <span class=\"token operator\">=</span> <span class=\"token keyword\">await</span> EmailPassword<span class=\"token punctuation\">.</span><span class=\"token function\">getUserByEmail</span><span class=\"token punctuation\">(</span>email<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n \n  <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span><span class=\"token operator\">!</span>user<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token comment\">// User not migrated - check Clerk</span>\n    <span class=\"token keyword\">const</span> clerkUser <span class=\"token operator\">=</span> <span class=\"token keyword\">await</span> clerk<span class=\"token punctuation\">.</span>users<span class=\"token punctuation\">.</span><span class=\"token function\">getUser</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">{</span> <span class=\"token literal-property property\">emailAddress</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">[</span>email<span class=\"token punctuation\">]</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n   \n    <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>clerkUser <span class=\"token operator\">&amp;&amp;</span> <span class=\"token keyword\">await</span> clerk<span class=\"token punctuation\">.</span><span class=\"token function\">verifyPassword</span><span class=\"token punctuation\">(</span>clerkUser<span class=\"token punctuation\">.</span>id<span class=\"token punctuation\">,</span> password<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n      <span class=\"token comment\">// Import to SuperTokens</span>\n      <span class=\"token keyword\">await</span> <span class=\"token function\">fetch</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"http://localhost:3567/bulk-import/users\"</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">{</span>\n        <span class=\"token literal-property property\">method</span><span class=\"token operator\">:</span> <span class=\"token string\">\"POST\"</span><span class=\"token punctuation\">,</span>\n        <span class=\"token literal-property property\">body</span><span class=\"token operator\">:</span> <span class=\"token constant\">JSON</span><span class=\"token punctuation\">.</span><span class=\"token function\">stringify</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">{</span>\n          <span class=\"token literal-property property\">users</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">[</span><span class=\"token punctuation\">{</span>\n            <span class=\"token literal-property property\">externalUserId</span><span class=\"token operator\">:</span> clerkUser<span class=\"token punctuation\">.</span>id<span class=\"token punctuation\">,</span>\n            <span class=\"token literal-property property\">loginMethods</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">[</span><span class=\"token punctuation\">{</span>\n              <span class=\"token literal-property property\">email</span><span class=\"token operator\">:</span> clerkUser<span class=\"token punctuation\">.</span>emailAddresses<span class=\"token punctuation\">[</span><span class=\"token number\">0</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">.</span>emailAddress<span class=\"token punctuation\">,</span>\n              <span class=\"token literal-property property\">passwordHash</span><span class=\"token operator\">:</span> clerkUser<span class=\"token punctuation\">.</span>passwordDigest<span class=\"token punctuation\">,</span>\n              <span class=\"token literal-property property\">hashingAlgorithm</span><span class=\"token operator\">:</span> <span class=\"token string\">\"bcrypt\"</span><span class=\"token punctuation\">,</span>\n            <span class=\"token punctuation\">}</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span>\n          <span class=\"token punctuation\">}</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span>\n        <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n      <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n     \n      user <span class=\"token operator\">=</span> <span class=\"token keyword\">await</span> EmailPassword<span class=\"token punctuation\">.</span><span class=\"token function\">getUserByEmail</span><span class=\"token punctuation\">(</span>email<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token punctuation\">}</span>\n  <span class=\"token punctuation\">}</span>\n \n  <span class=\"token comment\">// Create SuperTokens session</span>\n  <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>user<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">await</span> Session<span class=\"token punctuation\">.</span><span class=\"token function\">createNewSession</span><span class=\"token punctuation\">(</span>req<span class=\"token punctuation\">,</span> res<span class=\"token punctuation\">,</span> user<span class=\"token punctuation\">.</span>id<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    res<span class=\"token punctuation\">.</span><span class=\"token function\">json</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">{</span> <span class=\"token literal-property property\">status</span><span class=\"token operator\">:</span> <span class=\"token string\">\"OK\"</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n  <span class=\"token punctuation\">}</span> <span class=\"token keyword\">else</span> <span class=\"token punctuation\">{</span>\n    res<span class=\"token punctuation\">.</span><span class=\"token function\">status</span><span class=\"token punctuation\">(</span><span class=\"token number\">401</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">json</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">{</span> <span class=\"token literal-property property\">error</span><span class=\"token operator\">:</span> <span class=\"token string\">\"Invalid credentials\"</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n  <span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></code></pre></div>\n<h3 id=\"bulk-import-use-case\" style=\"position:relative;\"><a href=\"#bulk-import-use-case\" aria-label=\"bulk import use case permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a><strong>Bulk Import Use Case</strong></h3>\n<p>Execute bulk imports for complete user base migration:</p>\n<div\n              class=\"gatsby-code-button-container\"\n              data-toaster-id=\"18787523295343500000\"\n              data-toaster-class=\"gatsby-code-button-toaster\"\n              data-toaster-text-class=\"gatsby-code-button-toaster-text\"\n              data-toaster-text=\"Copied!\"\n              data-toaster-duration=\"3500\"\n              onClick=\"copyToClipboard(`import fs from &quot;fs&quot;;\n\n\nasync function bulkImportUsers() {\n  const clerkUsers = JSON.parse(fs.readFileSync(&quot;clerk_export.json&quot;));\n \n  // Transform to SuperTokens format\n  const superTokensUsers = clerkUsers.map(u => ({\n    externalUserId: u.id,\n    loginMethods: [{\n      email: u.email_addresses[0].email_address,\n      passwordHash: u.password_hash,\n      hashingAlgorithm: &quot;bcrypt&quot;,\n    }],\n    totpDevices: u.totp_secrets?.map(s => ({\n      secretKey: s.secret,\n      deviceName: &quot;Migrated Device&quot;,\n    })) || [],\n  }));\n \n  // Import in batches of 10,000\n  const batchSize = 10000;\n  for (let i = 0; i < superTokensUsers.length; i += batchSize) {\n    const batch = superTokensUsers.slice(i, i + batchSize);\n   \n    await fetch(&quot;http://localhost:3567/bulk-import/users&quot;, {\n      method: &quot;POST&quot;,\n      headers: { &quot;Content-Type&quot;: &quot;application/json&quot; },\n      body: JSON.stringify({ users: batch }),\n    });\n  }\n}`, `18787523295343500000`)\"\n            >\n              <div\n                class=\"gatsby-code-button\"\n                data-tooltip=\"\"\n              >\n                <svg class=\"gatsby-code-button-icon\" xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\"><path fill=\"none\" d=\"M0 0h24v24H0V0z\"/><path d=\"M16 1H2v16h2V3h12V1zm-1 4l6 6v12H6V5h9zm-1 7h5.5L14 6.5V12z\"/></svg>\n              </div>\n            </div>\n<div class=\"gatsby-highlight\" data-language=\"js\"><pre class=\"language-js\"><code class=\"language-js\"><span class=\"token keyword\">import</span> fs <span class=\"token keyword\">from</span> <span class=\"token string\">\"fs\"</span><span class=\"token punctuation\">;</span>\n\n\n<span class=\"token keyword\">async</span> <span class=\"token keyword\">function</span> <span class=\"token function\">bulkImportUsers</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n  <span class=\"token keyword\">const</span> clerkUsers <span class=\"token operator\">=</span> <span class=\"token constant\">JSON</span><span class=\"token punctuation\">.</span><span class=\"token function\">parse</span><span class=\"token punctuation\">(</span>fs<span class=\"token punctuation\">.</span><span class=\"token function\">readFileSync</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"clerk_export.json\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n \n  <span class=\"token comment\">// Transform to SuperTokens format</span>\n  <span class=\"token keyword\">const</span> superTokensUsers <span class=\"token operator\">=</span> clerkUsers<span class=\"token punctuation\">.</span><span class=\"token function\">map</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">u</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">{</span>\n    <span class=\"token literal-property property\">externalUserId</span><span class=\"token operator\">:</span> u<span class=\"token punctuation\">.</span>id<span class=\"token punctuation\">,</span>\n    <span class=\"token literal-property property\">loginMethods</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">[</span><span class=\"token punctuation\">{</span>\n      <span class=\"token literal-property property\">email</span><span class=\"token operator\">:</span> u<span class=\"token punctuation\">.</span>email_addresses<span class=\"token punctuation\">[</span><span class=\"token number\">0</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">.</span>email_address<span class=\"token punctuation\">,</span>\n      <span class=\"token literal-property property\">passwordHash</span><span class=\"token operator\">:</span> u<span class=\"token punctuation\">.</span>password_hash<span class=\"token punctuation\">,</span>\n      <span class=\"token literal-property property\">hashingAlgorithm</span><span class=\"token operator\">:</span> <span class=\"token string\">\"bcrypt\"</span><span class=\"token punctuation\">,</span>\n    <span class=\"token punctuation\">}</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span>\n    <span class=\"token literal-property property\">totpDevices</span><span class=\"token operator\">:</span> u<span class=\"token punctuation\">.</span>totp_secrets<span class=\"token operator\">?.</span><span class=\"token function\">map</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">s</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">{</span>\n      <span class=\"token literal-property property\">secretKey</span><span class=\"token operator\">:</span> s<span class=\"token punctuation\">.</span>secret<span class=\"token punctuation\">,</span>\n      <span class=\"token literal-property property\">deviceName</span><span class=\"token operator\">:</span> <span class=\"token string\">\"Migrated Device\"</span><span class=\"token punctuation\">,</span>\n    <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">||</span> <span class=\"token punctuation\">[</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span>\n  <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n \n  <span class=\"token comment\">// Import in batches of 10,000</span>\n  <span class=\"token keyword\">const</span> batchSize <span class=\"token operator\">=</span> <span class=\"token number\">10000</span><span class=\"token punctuation\">;</span>\n  <span class=\"token keyword\">for</span> <span class=\"token punctuation\">(</span><span class=\"token keyword\">let</span> i <span class=\"token operator\">=</span> <span class=\"token number\">0</span><span class=\"token punctuation\">;</span> i <span class=\"token operator\">&lt;</span> superTokensUsers<span class=\"token punctuation\">.</span>length<span class=\"token punctuation\">;</span> i <span class=\"token operator\">+=</span> batchSize<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">const</span> batch <span class=\"token operator\">=</span> superTokensUsers<span class=\"token punctuation\">.</span><span class=\"token function\">slice</span><span class=\"token punctuation\">(</span>i<span class=\"token punctuation\">,</span> i <span class=\"token operator\">+</span> batchSize<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n   \n    <span class=\"token keyword\">await</span> <span class=\"token function\">fetch</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"http://localhost:3567/bulk-import/users\"</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">{</span>\n      <span class=\"token literal-property property\">method</span><span class=\"token operator\">:</span> <span class=\"token string\">\"POST\"</span><span class=\"token punctuation\">,</span>\n      <span class=\"token literal-property property\">headers</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">{</span> <span class=\"token string-property property\">\"Content-Type\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"application/json\"</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span>\n      <span class=\"token literal-property property\">body</span><span class=\"token operator\">:</span> <span class=\"token constant\">JSON</span><span class=\"token punctuation\">.</span><span class=\"token function\">stringify</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">{</span> <span class=\"token literal-property property\">users</span><span class=\"token operator\">:</span> batch <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n    <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n  <span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<p><strong>Monitor Import Progress:</strong></p>\n<div\n              class=\"gatsby-code-button-container\"\n              data-toaster-id=\"53192267771917165000\"\n              data-toaster-class=\"gatsby-code-button-toaster\"\n              data-toaster-text-class=\"gatsby-code-button-toaster-text\"\n              data-toaster-text=\"Copied!\"\n              data-toaster-duration=\"3500\"\n              onClick=\"copyToClipboard(`// Check status\nconst response = await fetch(&quot;http://localhost:3567/bulk-import/users/status&quot;);\nconst status = await response.json();\n\n\nconsole.log(\\`Total: \\${status.stats.total}, Success: \\${status.stats.success}, Failed: \\${status.stats.failed}\\`);`, `53192267771917165000`)\"\n            >\n              <div\n                class=\"gatsby-code-button\"\n                data-tooltip=\"\"\n              >\n                <svg class=\"gatsby-code-button-icon\" xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\"><path fill=\"none\" d=\"M0 0h24v24H0V0z\"/><path d=\"M16 1H2v16h2V3h12V1zm-1 4l6 6v12H6V5h9zm-1 7h5.5L14 6.5V12z\"/></svg>\n              </div>\n            </div>\n<div class=\"gatsby-highlight\" data-language=\"js\"><pre class=\"language-js\"><code class=\"language-js\"><span class=\"token comment\">// Check status</span>\n<span class=\"token keyword\">const</span> response <span class=\"token operator\">=</span> <span class=\"token keyword\">await</span> <span class=\"token function\">fetch</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"http://localhost:3567/bulk-import/users/status\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">const</span> status <span class=\"token operator\">=</span> <span class=\"token keyword\">await</span> response<span class=\"token punctuation\">.</span><span class=\"token function\">json</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n\nconsole<span class=\"token punctuation\">.</span><span class=\"token function\">log</span><span class=\"token punctuation\">(</span><span class=\"token template-string\"><span class=\"token template-punctuation string\">`</span><span class=\"token string\">Total: </span><span class=\"token interpolation\"><span class=\"token interpolation-punctuation punctuation\">${</span>status<span class=\"token punctuation\">.</span>stats<span class=\"token punctuation\">.</span>total<span class=\"token interpolation-punctuation punctuation\">}</span></span><span class=\"token string\">, Success: </span><span class=\"token interpolation\"><span class=\"token interpolation-punctuation punctuation\">${</span>status<span class=\"token punctuation\">.</span>stats<span class=\"token punctuation\">.</span>success<span class=\"token interpolation-punctuation punctuation\">}</span></span><span class=\"token string\">, Failed: </span><span class=\"token interpolation\"><span class=\"token interpolation-punctuation punctuation\">${</span>status<span class=\"token punctuation\">.</span>stats<span class=\"token punctuation\">.</span>failed<span class=\"token interpolation-punctuation punctuation\">}</span></span><span class=\"token template-punctuation string\">`</span></span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></code></pre></div>\n<h2 id=\"handling-sessions-mfa-and-other-edge-cases\" style=\"position:relative;\"><a href=\"#handling-sessions-mfa-and-other-edge-cases\" aria-label=\"handling sessions mfa and other edge cases permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a><strong>Handling Sessions, MFA, and Other Edge Cases</strong></h2>\n<h3 id=\"migrating-session-state\" style=\"position:relative;\"><a href=\"#migrating-session-state\" aria-label=\"migrating session state permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a><strong>Migrating Session State</strong></h3>\n<p>Active Clerk sessions do not transfer to SuperTokens. Users with valid Clerk sessions continue working until expiration; the next login triggers migration and SuperTokens session creation.</p>\n<p><strong>Session Fallback Logic:</strong></p>\n<p>During transition, implement verification fallback:</p>\n<div\n              class=\"gatsby-code-button-container\"\n              data-toaster-id=\"11410363251567546000\"\n              data-toaster-class=\"gatsby-code-button-toaster\"\n              data-toaster-text-class=\"gatsby-code-button-toaster-text\"\n              data-toaster-text=\"Copied!\"\n              data-toaster-duration=\"3500\"\n              onClick=\"copyToClipboard(`async function verifySessionWithFallback(req, res, next) {\n  try {\n    await verifySession()(req, res, next);\n  } catch (error) {\n    // Try Clerk session as fallback\n    const clerkSession = await clerk.sessions.verifySession(req.cookies.__session);\n    if (clerkSession) {\n      req.clerkUserId = clerkSession.userId;\n      next();\n    } else {\n      res.status(401).json({ error: &quot;Unauthorized&quot; });\n    }\n  }\n}`, `11410363251567546000`)\"\n            >\n              <div\n                class=\"gatsby-code-button\"\n                data-tooltip=\"\"\n              >\n                <svg class=\"gatsby-code-button-icon\" xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\"><path fill=\"none\" d=\"M0 0h24v24H0V0z\"/><path d=\"M16 1H2v16h2V3h12V1zm-1 4l6 6v12H6V5h9zm-1 7h5.5L14 6.5V12z\"/></svg>\n              </div>\n            </div>\n<div class=\"gatsby-highlight\" data-language=\"js\"><pre class=\"language-js\"><code class=\"language-js\"><span class=\"token keyword\">async</span> <span class=\"token keyword\">function</span> <span class=\"token function\">verifySessionWithFallback</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">req<span class=\"token punctuation\">,</span> res<span class=\"token punctuation\">,</span> next</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n  <span class=\"token keyword\">try</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">await</span> <span class=\"token function\">verifySession</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">(</span>req<span class=\"token punctuation\">,</span> res<span class=\"token punctuation\">,</span> next<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n  <span class=\"token punctuation\">}</span> <span class=\"token keyword\">catch</span> <span class=\"token punctuation\">(</span>error<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token comment\">// Try Clerk session as fallback</span>\n    <span class=\"token keyword\">const</span> clerkSession <span class=\"token operator\">=</span> <span class=\"token keyword\">await</span> clerk<span class=\"token punctuation\">.</span>sessions<span class=\"token punctuation\">.</span><span class=\"token function\">verifySession</span><span class=\"token punctuation\">(</span>req<span class=\"token punctuation\">.</span>cookies<span class=\"token punctuation\">.</span>__session<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>clerkSession<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n      req<span class=\"token punctuation\">.</span>clerkUserId <span class=\"token operator\">=</span> clerkSession<span class=\"token punctuation\">.</span>userId<span class=\"token punctuation\">;</span>\n      <span class=\"token function\">next</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token punctuation\">}</span> <span class=\"token keyword\">else</span> <span class=\"token punctuation\">{</span>\n      res<span class=\"token punctuation\">.</span><span class=\"token function\">status</span><span class=\"token punctuation\">(</span><span class=\"token number\">401</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">json</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">{</span> <span class=\"token literal-property property\">error</span><span class=\"token operator\">:</span> <span class=\"token string\">\"Unauthorized\"</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token punctuation\">}</span>\n  <span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<h3 id=\"mfatotp-data\" style=\"position:relative;\"><a href=\"#mfatotp-data\" aria-label=\"mfatotp data permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a><strong>MFA/TOTP Data</strong></h3>\n<p>Multi-factor authentication secrets must be preserved to avoid forcing users to re-enroll.</p>\n<p><strong>Export from Clerk:</strong></p>\n<p>Clerk exports include TOTP secrets in user data:</p>\n<div\n              class=\"gatsby-code-button-container\"\n              data-toaster-id=\"46727918205966750000\"\n              data-toaster-class=\"gatsby-code-button-toaster\"\n              data-toaster-text-class=\"gatsby-code-button-toaster-text\"\n              data-toaster-text=\"Copied!\"\n              data-toaster-duration=\"3500\"\n              onClick=\"copyToClipboard(`{\n  &quot;totp_secrets&quot;: [\n    {\n      &quot;secret&quot;: &quot;JBSWY3DPEHPK3PXP&quot;,\n      &quot;verified&quot;: true\n    }\n  ]\n}`, `46727918205966750000`)\"\n            >\n              <div\n                class=\"gatsby-code-button\"\n                data-tooltip=\"\"\n              >\n                <svg class=\"gatsby-code-button-icon\" xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\"><path fill=\"none\" d=\"M0 0h24v24H0V0z\"/><path d=\"M16 1H2v16h2V3h12V1zm-1 4l6 6v12H6V5h9zm-1 7h5.5L14 6.5V12z\"/></svg>\n              </div>\n            </div>\n<div class=\"gatsby-highlight\" data-language=\"js\"><pre class=\"language-js\"><code class=\"language-js\"><span class=\"token punctuation\">{</span>\n  <span class=\"token string-property property\">\"totp_secrets\"</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">[</span>\n    <span class=\"token punctuation\">{</span>\n      <span class=\"token string-property property\">\"secret\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"JBSWY3DPEHPK3PXP\"</span><span class=\"token punctuation\">,</span>\n      <span class=\"token string-property property\">\"verified\"</span><span class=\"token operator\">:</span> <span class=\"token boolean\">true</span>\n    <span class=\"token punctuation\">}</span>\n  <span class=\"token punctuation\">]</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<p><strong>Import to SuperTokens:</strong></p>\n<p>Include TOTP devices in the bulk import:</p>\n<div\n              class=\"gatsby-code-button-container\"\n              data-toaster-id=\"84874078069214410000\"\n              data-toaster-class=\"gatsby-code-button-toaster\"\n              data-toaster-text-class=\"gatsby-code-button-toaster-text\"\n              data-toaster-text=\"Copied!\"\n              data-toaster-duration=\"3500\"\n              onClick=\"copyToClipboard(`{\n  &quot;totpDevices&quot;: [\n    {\n      &quot;secretKey&quot;: &quot;JBSWY3DPEHPK3PXP&quot;,\n      &quot;deviceName&quot;: &quot;Authenticator App&quot;,\n      &quot;verified&quot;: true\n    }\n  ]\n}`, `84874078069214410000`)\"\n            >\n              <div\n                class=\"gatsby-code-button\"\n                data-tooltip=\"\"\n              >\n                <svg class=\"gatsby-code-button-icon\" xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\"><path fill=\"none\" d=\"M0 0h24v24H0V0z\"/><path d=\"M16 1H2v16h2V3h12V1zm-1 4l6 6v12H6V5h9zm-1 7h5.5L14 6.5V12z\"/></svg>\n              </div>\n            </div>\n<div class=\"gatsby-highlight\" data-language=\"js\"><pre class=\"language-js\"><code class=\"language-js\"><span class=\"token punctuation\">{</span>\n  <span class=\"token string-property property\">\"totpDevices\"</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">[</span>\n    <span class=\"token punctuation\">{</span>\n      <span class=\"token string-property property\">\"secretKey\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"JBSWY3DPEHPK3PXP\"</span><span class=\"token punctuation\">,</span>\n      <span class=\"token string-property property\">\"deviceName\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"Authenticator App\"</span><span class=\"token punctuation\">,</span>\n      <span class=\"token string-property property\">\"verified\"</span><span class=\"token operator\">:</span> <span class=\"token boolean\">true</span>\n    <span class=\"token punctuation\">}</span>\n  <span class=\"token punctuation\">]</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<h3 id=\"ensuring-userid-continuity\" style=\"position:relative;\"><a href=\"#ensuring-userid-continuity\" aria-label=\"ensuring userid continuity permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a><strong>Ensuring userId Continuity</strong></h3>\n<p>Maintain user ID consistency to preserve foreign key relationships in your application database.</p>\n<p><strong>Strategy:</strong></p>\n<p>Use the Clerk’s user ID as the SuperTokens’ <code class=\"language-text\">externalUserId</code>:</p>\n<div\n              class=\"gatsby-code-button-container\"\n              data-toaster-id=\"99967924561159800000\"\n              data-toaster-class=\"gatsby-code-button-toaster\"\n              data-toaster-text-class=\"gatsby-code-button-toaster-text\"\n              data-toaster-text=\"Copied!\"\n              data-toaster-duration=\"3500\"\n              onClick=\"copyToClipboard(`{\n  &quot;externalUserId&quot;: &quot;clerk_user_2abc123&quot;\n}`, `99967924561159800000`)\"\n            >\n              <div\n                class=\"gatsby-code-button\"\n                data-tooltip=\"\"\n              >\n                <svg class=\"gatsby-code-button-icon\" xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\"><path fill=\"none\" d=\"M0 0h24v24H0V0z\"/><path d=\"M16 1H2v16h2V3h12V1zm-1 4l6 6v12H6V5h9zm-1 7h5.5L14 6.5V12z\"/></svg>\n              </div>\n            </div>\n<div class=\"gatsby-highlight\" data-language=\"js\"><pre class=\"language-js\"><code class=\"language-js\"><span class=\"token punctuation\">{</span>\n  <span class=\"token string-property property\">\"externalUserId\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"clerk_user_2abc123\"</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<p><strong>Access External User ID:</strong></p>\n<div\n              class=\"gatsby-code-button-container\"\n              data-toaster-id=\"69031448200537326000\"\n              data-toaster-class=\"gatsby-code-button-toaster\"\n              data-toaster-text-class=\"gatsby-code-button-toaster-text\"\n              data-toaster-text=\"Copied!\"\n              data-toaster-duration=\"3500\"\n              onClick=\"copyToClipboard(`const users = await SuperTokens.getUsersOldestFirst({\n  externalUserId: clerkUserId,\n});\nconst user = users.users[0];`, `69031448200537326000`)\"\n            >\n              <div\n                class=\"gatsby-code-button\"\n                data-tooltip=\"\"\n              >\n                <svg class=\"gatsby-code-button-icon\" xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\"><path fill=\"none\" d=\"M0 0h24v24H0V0z\"/><path d=\"M16 1H2v16h2V3h12V1zm-1 4l6 6v12H6V5h9zm-1 7h5.5L14 6.5V12z\"/></svg>\n              </div>\n            </div>\n<div class=\"gatsby-highlight\" data-language=\"js\"><pre class=\"language-js\"><code class=\"language-js\"><span class=\"token keyword\">const</span> users <span class=\"token operator\">=</span> <span class=\"token keyword\">await</span> SuperTokens<span class=\"token punctuation\">.</span><span class=\"token function\">getUsersOldestFirst</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">{</span>\n  <span class=\"token literal-property property\">externalUserId</span><span class=\"token operator\">:</span> clerkUserId<span class=\"token punctuation\">,</span>\n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">const</span> user <span class=\"token operator\">=</span> users<span class=\"token punctuation\">.</span>users<span class=\"token punctuation\">[</span><span class=\"token number\">0</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span></code></pre></div>\n<h2 id=\"recommended-rollout-steps\" style=\"position:relative;\"><a href=\"#recommended-rollout-steps\" aria-label=\"recommended rollout steps permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a><strong>Recommended Rollout Steps</strong></h2>\n<h3 id=\"1-prep-environment\" style=\"position:relative;\"><a href=\"#1-prep-environment\" aria-label=\"1 prep environment permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a><strong>1. Prep Environment</strong></h3>\n<p><strong>Set Up Staging:</strong></p>\n<ul>\n<li>Deploy SuperTokens instance (self-hosted or managed)</li>\n<li>Configure staging with both Clerk and SuperTokens</li>\n<li>Export sample users from Clerk production</li>\n<li>Import sample users into SuperTokens staging</li>\n</ul>\n<p><strong>Test Authentication Flows:</strong></p>\n<ul>\n<li>User registration</li>\n<li>Login</li>\n<li>Password reset</li>\n<li>MFA enrollment and verification</li>\n<li>Session management</li>\n</ul>\n<h3 id=\"2-enable-lazy-migration-first\" style=\"position:relative;\"><a href=\"#2-enable-lazy-migration-first\" aria-label=\"2 enable lazy migration first permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a><strong>2. Enable Lazy Migration First</strong></h3>\n<p><strong>Timeline:</strong></p>\n<ul>\n<li>Week 1-2: Deploy lazy migration to staging and test</li>\n<li>Week 3: Deploy to production with feature flag</li>\n<li>Week 4+: Monitor migration metrics</li>\n</ul>\n<p><strong>Key Metrics:</strong></p>\n<ul>\n<li>Total users migrated</li>\n<li>Daily migration rate</li>\n<li>Migration failures</li>\n<li>Average migration time</li>\n</ul>\n<h3 id=\"3-bulk-import-the-rest\" style=\"position:relative;\"><a href=\"#3-bulk-import-the-rest\" aria-label=\"3 bulk import the rest permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a><strong>3. Bulk-Import the Rest</strong></h3>\n<p>After lazy migration stabilizes (typically 2-4 weeks):</p>\n<ol>\n<li>Export complete user list from Clerk.</li>\n<li>Filter out already-migrated users.</li>\n<li>Execute bulk import in batches.</li>\n<li>Monitor import job status.</li>\n<li>Verify data integrity.</li>\n<li>Handle failed imports.</li>\n</ol>\n<h3 id=\"4-developer-and-ux-testing\" style=\"position:relative;\"><a href=\"#4-developer-and-ux-testing\" aria-label=\"4 developer and ux testing permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a><strong>4. Developer and UX Testing</strong></h3>\n<p><strong>Test Checklist:</strong></p>\n<ul>\n<li>Registration creates SuperTokens account</li>\n<li>Login authenticates against SuperTokens</li>\n<li>Password reset works end-to-end</li>\n<li>MFA functions correctly</li>\n<li>Role-based access control enforced</li>\n<li>Session refresh works</li>\n<li>Profile updates persist</li>\n<li>Email verification completes</li>\n</ul>\n<h3 id=\"5-final-cutover\" style=\"position:relative;\"><a href=\"#5-final-cutover\" aria-label=\"5 final cutover permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a><strong>5. Final Cutover</strong></h3>\n<p><strong>Remove Clerk Dependencies:</strong></p>\n<div\n              class=\"gatsby-code-button-container\"\n              data-toaster-id=\"45233622035971470000\"\n              data-toaster-class=\"gatsby-code-button-toaster\"\n              data-toaster-text-class=\"gatsby-code-button-toaster-text\"\n              data-toaster-text=\"Copied!\"\n              data-toaster-duration=\"3500\"\n              onClick=\"copyToClipboard(`npm uninstall @clerk/nextjs @clerk/clerk-react @clerk/backend`, `45233622035971470000`)\"\n            >\n              <div\n                class=\"gatsby-code-button\"\n                data-tooltip=\"\"\n              >\n                <svg class=\"gatsby-code-button-icon\" xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\"><path fill=\"none\" d=\"M0 0h24v24H0V0z\"/><path d=\"M16 1H2v16h2V3h12V1zm-1 4l6 6v12H6V5h9zm-1 7h5.5L14 6.5V12z\"/></svg>\n              </div>\n            </div>\n<div class=\"gatsby-highlight\" data-language=\"js\"><pre class=\"language-js\"><code class=\"language-js\">npm uninstall @clerk<span class=\"token operator\">/</span>nextjs @clerk<span class=\"token operator\">/</span>clerk<span class=\"token operator\">-</span>react @clerk<span class=\"token operator\">/</span>backend</code></pre></div>\n<p><strong>Update Authentication Code:</strong></p>\n<div\n              class=\"gatsby-code-button-container\"\n              data-toaster-id=\"86415864448256330000\"\n              data-toaster-class=\"gatsby-code-button-toaster\"\n              data-toaster-text-class=\"gatsby-code-button-toaster-text\"\n              data-toaster-text=\"Copied!\"\n              data-toaster-duration=\"3500\"\n              onClick=\"copyToClipboard(`// Before (Clerk)\nimport { SignIn } from &quot;@clerk/nextjs&quot;;\n\n// After (SuperTokens)\nimport { EmailPasswordAuth } from &quot;supertokens-auth-react/recipe/emailpassword&quot;;`, `86415864448256330000`)\"\n            >\n              <div\n                class=\"gatsby-code-button\"\n                data-tooltip=\"\"\n              >\n                <svg class=\"gatsby-code-button-icon\" xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\"><path fill=\"none\" d=\"M0 0h24v24H0V0z\"/><path d=\"M16 1H2v16h2V3h12V1zm-1 4l6 6v12H6V5h9zm-1 7h5.5L14 6.5V12z\"/></svg>\n              </div>\n            </div>\n<div class=\"gatsby-highlight\" data-language=\"js\"><pre class=\"language-js\"><code class=\"language-js\"><span class=\"token comment\">// Before (Clerk)</span>\n<span class=\"token keyword\">import</span> <span class=\"token punctuation\">{</span> SignIn <span class=\"token punctuation\">}</span> <span class=\"token keyword\">from</span> <span class=\"token string\">\"@clerk/nextjs\"</span><span class=\"token punctuation\">;</span>\n\n<span class=\"token comment\">// After (SuperTokens)</span>\n<span class=\"token keyword\">import</span> <span class=\"token punctuation\">{</span> EmailPasswordAuth <span class=\"token punctuation\">}</span> <span class=\"token keyword\">from</span> <span class=\"token string\">\"supertokens-auth-react/recipe/emailpassword\"</span><span class=\"token punctuation\">;</span></code></pre></div>\n<p><strong>Communication:</strong></p>\n<ul>\n<li>Notify users of the authentication system upgrade.</li>\n<li>Update documentation.</li>\n<li>Inform the support team.</li>\n<li>Prepare a rollback plan.</li>\n</ul>\n<h2 id=\"benefits-of-migrating-to-supertokens\" style=\"position:relative;\"><a href=\"#benefits-of-migrating-to-supertokens\" aria-label=\"benefits of migrating to supertokens permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a><strong>Benefits of Migrating to SuperTokens</strong></h2>\n<h3 id=\"full-control-and-open-source\" style=\"position:relative;\"><a href=\"#full-control-and-open-source\" aria-label=\"full control and open source permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a><strong>Full Control and Open Source</strong></h3>\n<p>SuperTokens provides complete source code visibility. No black-boxauthentication logic—developers can audit every line, modify flows, and contribute improvements. Self-hosted deployments eliminate vendor lock-in and provide complete control over data residency, upgrades, and infrastructure.</p>\n<h3 id=\"customizable-authentication-flows\" style=\"position:relative;\"><a href=\"#customizable-authentication-flows\" aria-label=\"customizable authentication flows permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a><strong>Customizable Authentication Flows</strong></h3>\n<p>SuperTokens enables complete customization of authentication logic:</p>\n<ul>\n<li>Custom signup validation and business rules</li>\n<li>Modified password requirements</li>\n<li>Tailored password reset flows</li>\n<li>Custom MFA enrollment logic</li>\n<li>Session duration policies</li>\n<li>Custom claims in access tokens</li>\n</ul>\n<h3 id=\"cost-effective-and-scalable\" style=\"position:relative;\"><a href=\"#cost-effective-and-scalable\" aria-label=\"cost effective and scalable permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a><strong>Cost-Effective and Scalable</strong></h3>\n<p><strong>Pricing Comparison:</strong></p>\n<table>\n<thead>\n<tr>\n<th>Users</th>\n<th>Clerk</th>\n<th>SuperTokens (Self-Hosted)</th>\n<th>SuperTokens (Managed)</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>10k MAU</td>\n<td>Free</td>\n<td>Free</td>\n<td>$200/month</td>\n</tr>\n</tbody>\n</table>\n<p><strong>Key Advantage:</strong> Flat-rate pricing without per-user charges that scale exponentially.</p>\n<h3 id=\"built-in-migration-support\" style=\"position:relative;\"><a href=\"#built-in-migration-support\" aria-label=\"built in migration support permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a><strong>Built-In Migration Support</strong></h3>\n<p>SuperTokens provides official migration tooling:</p>\n<ul>\n<li>Bulk import API with batch processing</li>\n<li>Password hash compatibility for major algorithms</li>\n<li>MFA/TOTP secret import</li>\n<li>User metadata preservation</li>\n<li>External ID mapping for foreign key continuity</li>\n</ul>\n<h2 id=\"faq-and-troubleshooting\" style=\"position:relative;\"><a href=\"#faq-and-troubleshooting\" aria-label=\"faq and troubleshooting permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a><strong>FAQ and Troubleshooting</strong></h2>\n<h3 id=\"can-existing-sessions-persist-across-platforms\" style=\"position:relative;\"><a href=\"#can-existing-sessions-persist-across-platforms\" aria-label=\"can existing sessions persist across platforms permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a><strong>Can existing sessions persist across platforms?</strong></h3>\n<p>No. Active sessions cannot transfer between Clerk and SuperTokens, due to different token formats. However, lazy migration ensures minimal\ndisruption—users continue with Clerk sessions until expiration, then migrate on their next login.</p>\n<h3 id=\"how-to-import-mfa-secrets-securely\" style=\"position:relative;\"><a href=\"#how-to-import-mfa-secrets-securely\" aria-label=\"how to import mfa secrets securely permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a><strong>How to import MFA secrets securely?</strong></h3>\n<p>Include TOTP secrets under <code class=\"language-text\">totpDevices</code> in bulk import requests. SuperTokens stores MFA secrets encrypted at rest.</p>\n<p><strong>Security Best Practices:</strong></p>\n<ul>\n<li>Export over HTTPS only</li>\n<li>Store export files encrypted</li>\n<li>Delete exports immediately after import</li>\n<li>Audit MFA import events</li>\n<li>Verify TOTP functionality for sample users</li>\n</ul>\n<h3 id=\"what-about-rate-limits\" style=\"position:relative;\"><a href=\"#what-about-rate-limits\" aria-label=\"what about rate limits permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a><strong>What about rate limits?</strong></h3>\n<p><strong>Clerk:</strong> May impose rate limits on exports; migration scripts handle this with exponential backoff.</p>\n<p><strong>SuperTokens:</strong> Processes up to 10,000 users per batch. For larger datasets, submit multiple batches sequentially.</p>\n<h3 id=\"how-to-debug-import-failures\" style=\"position:relative;\"><a href=\"#how-to-debug-import-failures\" aria-label=\"how to debug import failures permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a><strong>How to debug import failures?</strong></h3>\n<p>Check failed imports via the status endpoint:</p>\n<div\n              class=\"gatsby-code-button-container\"\n              data-toaster-id=\"44946430525589200000\"\n              data-toaster-class=\"gatsby-code-button-toaster\"\n              data-toaster-text-class=\"gatsby-code-button-toaster-text\"\n              data-toaster-text=\"Copied!\"\n              data-toaster-duration=\"3500\"\n              onClick=\"copyToClipboard(`const response = await fetch(&quot;http://localhost:3567/bulk-import/users/status?status=FAILED&quot;);\nconst failedImports = await response.json();\n\nfailedImports.users.forEach(failed => {\n  console.error(\\`User \\${failed.externalUserId}: \\${failed.error}\\`);\n});`, `44946430525589200000`)\"\n            >\n              <div\n                class=\"gatsby-code-button\"\n                data-tooltip=\"\"\n              >\n                <svg class=\"gatsby-code-button-icon\" xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\"><path fill=\"none\" d=\"M0 0h24v24H0V0z\"/><path d=\"M16 1H2v16h2V3h12V1zm-1 4l6 6v12H6V5h9zm-1 7h5.5L14 6.5V12z\"/></svg>\n              </div>\n            </div>\n<div class=\"gatsby-highlight\" data-language=\"js\"><pre class=\"language-js\"><code class=\"language-js\"><span class=\"token keyword\">const</span> response <span class=\"token operator\">=</span> <span class=\"token keyword\">await</span> <span class=\"token function\">fetch</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"http://localhost:3567/bulk-import/users/status?status=FAILED\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">const</span> failedImports <span class=\"token operator\">=</span> <span class=\"token keyword\">await</span> response<span class=\"token punctuation\">.</span><span class=\"token function\">json</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\nfailedImports<span class=\"token punctuation\">.</span>users<span class=\"token punctuation\">.</span><span class=\"token function\">forEach</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">failed</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n  console<span class=\"token punctuation\">.</span><span class=\"token function\">error</span><span class=\"token punctuation\">(</span><span class=\"token template-string\"><span class=\"token template-punctuation string\">`</span><span class=\"token string\">User </span><span class=\"token interpolation\"><span class=\"token interpolation-punctuation punctuation\">${</span>failed<span class=\"token punctuation\">.</span>externalUserId<span class=\"token interpolation-punctuation punctuation\">}</span></span><span class=\"token string\">: </span><span class=\"token interpolation\"><span class=\"token interpolation-punctuation punctuation\">${</span>failed<span class=\"token punctuation\">.</span>error<span class=\"token interpolation-punctuation punctuation\">}</span></span><span class=\"token template-punctuation string\">`</span></span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></code></pre></div>\n<p><strong>Common Issues:</strong></p>\n<table>\n<thead>\n<tr>\n<th>Error</th>\n<th>Solution</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>“Invalid password hash”</td>\n<td>Convert hashes or require password reset.</td>\n</tr>\n<tr>\n<td>“Duplicate email”</td>\n<td>Skip or update existing user.</td>\n</tr>\n<tr>\n<td>“Missing required field”</td>\n<td>Fix data transformation logic.</td>\n</tr>\n<tr>\n<td>“Invalid TOTP secret”</td>\n<td>Verify secret encoding.</td>\n</tr>\n</tbody>\n</table>\n<h2 id=\"conclusion-and-next-steps\" style=\"position:relative;\"><a href=\"#conclusion-and-next-steps\" aria-label=\"conclusion and next steps permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a><strong>Conclusion and Next Steps</strong></h2>\n<p>Migrating from Clerk to SuperTokens involves strategic planning, careful data handling, and systematic rollout. Key approaches include:</p>\n<ul>\n<li><strong>Lazy/Trickle Migration</strong>: Incremental migration upon login, targeting active users first.</li>\n<li><strong>Bulk Import</strong>: Upfront migration via API for faster Clerk deprecation.</li>\n<li><strong>Hybrid Approach</strong>: Combining both methods for optimal results.</li>\n</ul>\n<p><strong>Critical Considerations:</strong></p>\n<ul>\n<li>Preserve MFA secrets to avoid forcing re-enrollment.</li>\n<li>Implement session fallback during transition.</li>\n<li>Use Clerk user IDs as SuperTokens external IDs for continuity.</li>\n<li>SuperTokens supports bcrypt, argon2, scrypt, and other hash algorithms.</li>\n</ul>\n<p><strong>SuperTokens Advantages:</strong></p>\n<ul>\n<li>Open source with full code visibility</li>\n<li>Self-hosting eliminates vendor lock-in</li>\n<li>Flat-rate pricing vs. per-user charges</li>\n<li>Deep customization of all authentication flows</li>\n<li>Built-in migration support</li>\n</ul>\n<p><strong>Next Steps:</strong></p>\n<ol>\n<li>Review the official SuperTokens migration docs at: <a href=\"https://supertokens.com/docs/emailpassword/migration/about\" target=\"_blank\" rel=\"nofollow\">https://supertokens.com/docs/emailpassword/migration/about</a>.</li>\n<li>Set-up staging environment with both systems.</li>\n<li>Export sample users and test migration scripts.</li>\n<li>Start with lazy migration for low-risk rollout.</li>\n<li>Schedule bulk import after validation.</li>\n<li>Join the SuperTokens Discord for migration support.</li>\n</ol>\n<p>With proper planning and the strategies outlined in this guide, you can transition smoothly from Clerk to SuperTokens while maintaining\nsecurity, preserving user data, and minimizing disruption.</p>","frontmatter":{"date":"January 12, 2026","title":"How to Migrate from Clerk Efficiently and Safely","cover":"clerk-migration.png","author":"Mostafa Ibrahim","description":" Step-by-step guide on migrating from Clerk to SuperTokens—covering trickle, bulk import, export scripts, sessions, and security."},"fields":{"slug":"/clerk-migration/"}},"site":{"siteMetadata":{"title":"SuperTokens Blog"}}},"pageContext":{"id":"a94e3a56-cbc0-5f3f-9c98-ad736007ddaf","fields__slug":"/clerk-migration/","__params":{"fields__slug":"clerk-migration"}}},
    "staticQueryHashes": []}