# Clerk vs AWS Cognito: Developer Experience vs Scale Economics - Part 2

> Part 2 of 3. Start with [Clerk vs AWS Cognito: Developer Experience vs Scale Economics](https://clerk.com/articles/clerk-vs-aws-cognito-developer-experience-vs-scale-economics.md).

This is the second part of a three-part series comparing Clerk and AWS Cognito. [Part 1](https://clerk.com/articles/clerk-vs-aws-cognito-developer-experience-vs-scale-economics.md) covered the core platform differences and developer experience. In this part, we focus on the architectural comparison and enterprise capabilities like B2B multi-tenancy, SSO, RBAC, and Directory Sync. Part 3 will cover scale economics and vendor lock-in.

## Architecture and feature comparison

Clerk is a developer-experience-first auth platform built around drop-in components and a typed SDK; AWS Cognito is an identity primitive inside the AWS ecosystem that you assemble into a full auth experience. The table below credits Cognito where it genuinely leads: native AWS integration, identity pools that issue temporary AWS credentials, and the lowest raw per-MAU price at very high volume. Every factual cell here is auditable to a primary source cited inline in the sections that follow, with the full pricing breakdown in [Part 3](https://clerk.com/articles/clerk-vs-aws-cognito-developer-experience-vs-scale-economics-3.md#scale-economics-implementation-cost-vs-cost-of-ownership).

| Dimension                                                                    | Clerk                                                                                                                                                                                                                                                                                                                                                                                                                | AWS Cognito                                                                                                                                                                                                                                                                                                                                                             |
| ---------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Developer experience                                                         | Components-first: prebuilt UI, hooks, and a typed SDK get production auth running in hours.                                                                                                                                                                                                                                                                                                                          | Infrastructure primitive: you assemble UI and flows on top of the SDK or Amplify.                                                                                                                                                                                                                                                                                       |
| Prebuilt UI components                                                       | Drop-in `<SignIn />`, `<UserButton />`, `<OrganizationSwitcher />`, plus profile and MFA flows.                                                                                                                                                                                                                                                                                                                      | Managed login (hosted UI) or build your own. No drop-in profile or org components.                                                                                                                                                                                                                                                                                      |
| Setup time (consumer auth)                                                   | About 4-12 hours (estimate).                                                                                                                                                                                                                                                                                                                                                                                         | About 40-80 hours (estimate).                                                                                                                                                                                                                                                                                                                                           |
| Local dev and testing                                                        | Paste `pk_test_`/`sk_test_` keys, no infra. Deterministic test users via `+clerk_test` and OTP `424242`.                                                                                                                                                                                                                                                                                                             | No official emulator. Use a real pool, LocalStack (paid), or `cognito-local` (feature gaps).                                                                                                                                                                                                                                                                            |
| Server-side framework support (RSC, Server Actions, `use cache`)             | Call `auth()` directly in Server Components, Actions, and Route Handlers. Next.js 16-aware.                                                                                                                                                                                                                                                                                                                          | Supported through Amplify's `runWithAmplifyServerContext(...)` wrapper. Works, but more ceremony.                                                                                                                                                                                                                                                                       |
| B2B organizations / multi-tenancy                                            | Native organizations: members, roles, invites, org switching, and org-scoped SSO.                                                                                                                                                                                                                                                                                                                                    | No native org or tenant object. Emulate with pools, app clients, groups, or `custom:tenantID`.                                                                                                                                                                                                                                                                          |
| Enterprise SSO (SAML/OIDC)                                                   | Per-organization enterprise connections plus EASIE. One connection included on Pro, then tiered.                                                                                                                                                                                                                                                                                                                     | SAML and OIDC federation configured per pool. Operationally heavy for per-tenant SSO.                                                                                                                                                                                                                                                                                   |
| SCIM / Directory Sync                                                        | Directory Sync (SCIM) is GA and bundled free with each enterprise connection. Deprovisioning revokes sessions.                                                                                                                                                                                                                                                                                                       | No native SCIM. Build a serverless provisioning stack yourself.                                                                                                                                                                                                                                                                                                         |
| Webhooks / event sync                                                        | Built-in signed, retrying webhooks across the user, org, and session lifecycle (`user.created` and more), with a first-party DB-sync guide.                                                                                                                                                                                                                                                                          | Synchronous Lambda triggers plus CloudTrail-fed EventBridge. No native per-mutation signed webhook.                                                                                                                                                                                                                                                                     |
| [RBAC](https://clerk.com/glossary.md#role-based-access-control-rbac) / roles | Roles and permissions with default `org:admin`/`org:member` and up to 10 custom roles. Custom Role Sets need the B2B add-on.                                                                                                                                                                                                                                                                                         | Groups mapped to IAM roles (coarse). Fine-grained app permissions need Amazon Verified Permissions.                                                                                                                                                                                                                                                                     |
| MFA and passwordless                                                         | SMS, TOTP, and backup codes. Passkeys as a separate passwordless credential.                                                                                                                                                                                                                                                                                                                                         | Email, SMS, and TOTP MFA on Essentials. Passkeys on Essentials and up.                                                                                                                                                                                                                                                                                                  |
| Security and compliance                                                      | [SOC 2 Type 2 and HIPAA](https://clerk.com/features/security) since [2022](https://clerk.com/changelog/2022-05-06.md), plus GDPR/CCPA. [Bot protection](https://clerk.com/docs/guides/secure/bot-protection.md), [breached-password blocking](https://clerk.com/docs/guides/secure/password-protection-and-rules.md), and [brute-force lockout](https://clerk.com/docs/guides/secure/user-lockout.md) on every plan. | Inherits [AWS SOC/PCI](https://aws.amazon.com/compliance/services-in-scope/), [HIPAA eligibility, and FedRAMP](https://docs.aws.amazon.com/cognito/latest/developerguide/compliance-validation.html). At-rest encryption by default (optional customer-managed KMS). Advanced threat protection is the paid Plus tier; edge filtering is the separately billed AWS WAF. |
| Customization / branding                                                     | Themeable components via `appearance`, plus fully headless hooks.                                                                                                                                                                                                                                                                                                                                                    | Managed login handles visual styling only: no text/label edits, no custom HTML/CSS, no custom fields. Deeper branding means custom flows.                                                                                                                                                                                                                               |
| Framework SDK coverage                                                       | First-class SDKs for Next.js, React, React Router, Astro, TanStack Start, Expo, Vue/Nuxt, iOS/Android, and Chrome Extension, plus backend SDKs.                                                                                                                                                                                                                                                                      | AWS SDK and Amplify (AWS-shaped, framework-agnostic).                                                                                                                                                                                                                                                                                                                   |
| AWS-ecosystem integration                                                    | Standards-based tokens that integrate with any backend, not AWS-coupled.                                                                                                                                                                                                                                                                                                                                             | Genuine win: native IAM, Lambda triggers, API Gateway, and AppSync. Identity pools issue temporary AWS credentials directly.                                                                                                                                                                                                                                            |
| Data portability / lock-in                                                   | CSV export includes hashed passwords, programmatic export via the Backend API, and standards-based JWTs.                                                                                                                                                                                                                                                                                                             | Does not export password hashes. User pools are largely immutable after creation.                                                                                                                                                                                                                                                                                       |
| Pricing model                                                                | Per Monthly Retained User (MRU), which excludes sign-up-and-bounce users. 50K free.                                                                                                                                                                                                                                                                                                                                  | Per Monthly Active User (MAU) across Lite, Essentials, and Plus. 10K free for new pools.                                                                                                                                                                                                                                                                                |
| Pricing at scale                                                             | Cheaper than Cognito Essentials below about 208K users, with features bundled in.                                                                                                                                                                                                                                                                                                                                    | Genuine consideration: the Lite tier is the lowest raw per-user price at very high volume, though feature-limited.                                                                                                                                                                                                                                                      |
| Support / ecosystem                                                          | Dedicated auth vendor. The docs and framework SDKs are the product.                                                                                                                                                                                                                                                                                                                                                  | Backed by AWS support plans and the broad AWS ecosystem and community.                                                                                                                                                                                                                                                                                                  |

A deeper treatment of the enterprise feature gaps follows in the sections below.

## Enterprise capabilities: where Cognito gets hard

Enterprise auth is where the build-it-yourself cost on Cognito compounds. [Organizations](https://clerk.com/docs/guides/organizations/overview.md), per-tenant SSO, SCIM provisioning, and database sync are first-class and bundled in Clerk, while on Cognito each is a system you design, build, and maintain on primitives. Cognito can do all of it. The question is how much of it you want to own.

### B2B organizations and multi-tenancy

This is the biggest gap. Cognito has no native organization or tenant primitive. Teams emulate multi-tenancy with one of several [documented patterns](https://docs.aws.amazon.com/cognito/latest/developerguide/multi-tenant-application-best-practices.html): pool-per-tenant, app-client-per-tenant, group-based, or custom-attribute (`custom:tenantID`), and each one carries trade-offs.

The [group-based approach](https://docs.aws.amazon.com/cognito/latest/developerguide/group-based-multi-tenancy.html) runs into [hard caps](https://docs.aws.amazon.com/cognito/latest/developerguide/limits.html): 10,000 groups per pool, 100 groups per user, and no nesting. The shared-pool patterns carry an isolation gap, where a valid session can reach other tenant apps that trust the same pool. And per-tenant MFA or password policy isn't possible in a shared pool, since those settings live at the pool level.

Clerk ships organizations as first-class objects: members, roles, invitations, org switching, and org-scoped SSO. Users can belong to multiple organizations, with an Active Organization per browser tab. Drop in `<OrganizationSwitcher />` and the multi-tenant model is there.

### Enterprise SSO (SAML/OIDC)

Cognito supports SAML and OIDC federation. Credit where it's due: both protocols work, and the IdP catalog is broad. The friction is operational. Configuration is per pool, the [SP entity ID is pool-scoped](https://docs.aws.amazon.com/cognito/latest/developerguide/cognito-user-pools-saml-idp.html) (`urn:amazon:cognito:sp:<pool-id>`, the same value for every tenant), and there's no per-tenant ACS URL. SAML metadata is [cached for up to 6 hours](https://docs.aws.amazon.com/cognito/latest/developerguide/cognito-user-pools-saml-idp-things-to-know.html), which becomes a cert-rotation risk when an IdP rolls its signing certificate. The [default quota is 300 identity providers per pool](https://docs.aws.amazon.com/cognito/latest/developerguide/limits.html), adjustable to a published maximum of 1,000 — a hard ceiling if you dedicate one SAML connection per enterprise tenant.

Clerk offers per-organization [enterprise connections](https://clerk.com/docs/guides/configure/auth-strategies/enterprise-connections/overview.md) plus the EASIE pattern for Google Workspace and Microsoft Entra ID. One honest packaging note: a plain enterprise connection is included on Pro (1 free, then tiered), but org-linked connections require the B2B Authentication add-on ($100/mo, or $85/mo billed annually).

### RBAC, roles, and permissions

Cognito provides [groups mapped to IAM roles](https://docs.aws.amazon.com/cognito/latest/developerguide/cognito-user-pools-user-groups.html) (`cognito:groups`, `cognito:preferred_role`), which is coarse. Native fine-grained application permissions require Amazon Verified Permissions, which now supports Cognito group-based RBAC through Cedar policies. That's real capability, but you configure the entity type and author the policies yourself. It's a policy engine, not turnkey app permissions.

Clerk provides [roles and permissions](https://clerk.com/docs/guides/organizations/control-access/roles-and-permissions.md) in the `org:<feature>:<permission>` format, with default `org:admin` and `org:member` roles and up to 10 custom roles per instance. Custom Role Sets require the B2B Authentication add-on.

### SCIM and Directory Sync

Cognito has [no native SCIM](https://repost.aws/questions/QUVEldD-3wQn6AythY4wnW0Q/aws-cognito-user-pool-saml-scim-support). Provisioning and deprovisioning means building a serverless stack yourself. The representative shape is API Gateway plus Lambda — the same architecture as [AWS's own SCIM-for-Cognito sample](https://github.com/aws-samples/amazon-cognito-scim-user-management), which builds SCIM `/Users` endpoints on exactly that stack. A full build exposes `/Users` (and often `/Groups`) and drives `AdminCreateUser`, `AdminDisableUser`, and `AdminDeleteUser` under the hood; [heavier implementations](https://medium.com/awsblackbelt/implementing-scim-with-aws-cognito-a-serverless-adventure-1db603abc617) add Step Functions to orchestrate longer-running syncs. Then you maintain it across the quirks of every IdP that connects.

Clerk offers [Directory Sync (SCIM)](https://clerk.com/docs/guides/configure/auth-strategies/enterprise-connections/directory-sync.md), generally available ([core GA April 16 2026](https://clerk.com/changelog/2026-04-16-directory-sync.md); [group-to-role and custom-attribute mapping GA May 21 2026](https://clerk.com/changelog/2026-05-21-directory-sync-groups-attributes-ga.md)), bundled free with each enterprise connection. Deprovisioning immediately revokes all of a user's sessions, consistent with Clerk's session model, and fires a standard `user.updated` webhook. SCIM changes flow through the same handler as everything else.

### Keeping your database in sync

Clerk ships built-in, signed, automatically-retried [webhooks](https://clerk.com/docs/guides/development/webhooks/overview.md) for the full user, organization, and session lifecycle: `user.created`, `user.updated`, `user.deleted`, plus org and session events. They're delivered over [Svix](https://docs.svix.com/receiving/verifying-payloads/how) to any endpoint and verified with [`verifyWebhook()`](https://clerk.com/docs/reference/backend/verify-webhook.md) from `@clerk/nextjs/webhooks` (or `@clerk/backend/webhooks` for non-Next.js backends, same signature). There's a first-party [guide for syncing Clerk data to your database](https://clerk.com/docs/guides/development/webhooks/syncing.md). Consumers stay idempotent on the `svix-id` header.

Directory Sync reuses that same path. An IdP provision fires `user.created`, an attribute change fires `user.updated`, and a deprovision deactivates the user, revokes sessions, and fires `user.updated`. One handler covers both self-serve and enterprise-provisioned changes. (Note that `scim.*` events are dashboard-only diagnostics, not your sync feed.)

Cognito, to be fair, does have events. It offers synchronous in-flow [Lambda triggers](https://docs.aws.amazon.com/cognito/latest/developerguide/cognito-user-identity-pools-working-with-aws-lambda-triggers.html) (post-confirmation, post-authentication, pre-token-generation, and so on) that run inside auth flows and can block or modify them. It also has partial EventBridge coverage delivered via CloudTrail (`source: aws.cognito-idp`, which requires a trail and is best-effort). What's missing is a native, durable, signed webhook for every directory mutation. And there's a sharp named gap: an out-of-band `AdminUpdateUserAttributes` fires no DB-sync trigger at all — at most the email/phone verification-message sender runs, and only when a change needs re-verification — so a backend attribute write to a custom field can silently skip your sync.

### Standing up per-tenant SSO on Cognito

Here's the heavy-code contrast. To onboard one enterprise customer's SAML IdP on a shared pool, you orchestrate several calls and protect them with a lock.

```ts
import {
  CognitoIdentityProviderClient,
  CreateIdentityProviderCommand,
  DescribeUserPoolClientCommand,
  UpdateUserPoolClientCommand,
} from '@aws-sdk/client-cognito-identity-provider'

const client = new CognitoIdentityProviderClient({ region: 'us-east-1' })

async function onboardTenantSaml(opts: {
  poolId: string
  appClientId: string
  providerName: string // max 32 chars
  metadataUrl: string
  emailDomain: string
  callbackUrl: string
}) {
  // UpdateUserPoolClient is capped at 5 RPS per pool and is a destructive
  // full-replace. Two onboardings racing throw ConcurrentModificationException,
  // so serialize per pool.
  await acquirePerPoolLock(opts.poolId)
  try {
    // 1. Register the tenant's IdP.
    await client.send(
      new CreateIdentityProviderCommand({
        UserPoolId: opts.poolId,
        ProviderName: opts.providerName,
        ProviderType: 'SAML',
        ProviderDetails: { MetadataURL: opts.metadataUrl },
        AttributeMapping: { email: 'emailAddress' },
        IdpIdentifiers: [opts.emailDomain],
      }),
    )

    // 2. Read the current app client BEFORE writing.
    const { UserPoolClient: current } = await client.send(
      new DescribeUserPoolClientCommand({
        UserPoolId: opts.poolId,
        ClientId: opts.appClientId,
      }),
    )

    // 3. Echo back EVERY field or Cognito resets it to default.
    await client.send(
      new UpdateUserPoolClientCommand({
        UserPoolId: opts.poolId,
        ClientId: opts.appClientId,
        SupportedIdentityProviders: [
          ...(current?.SupportedIdentityProviders ?? []),
          opts.providerName,
        ],
        CallbackURLs: Array.from(new Set([...(current?.CallbackURLs ?? []), opts.callbackUrl])),
        // You must also re-send AllowedOAuthFlows, AllowedOAuthScopes,
        // ExplicitAuthFlows, token validities, and every other setting,
        // or they silently revert to defaults.
      }),
    )
  } finally {
    await releasePerPoolLock(opts.poolId)
  }

  // 4. And you still need a Pre-Token-Generation Lambda to stamp tenant_id,
  // a tenant registry mapping email domain to provider, and a sign-in
  // routing layer in front of all of it.
  await registerTenant(opts.emailDomain, opts.providerName)
}
```

That's the work for one tenant, and you own it forever. In Clerk you add one enterprise connection in the Dashboard, on the [SSO connections → Enterprise page](https://dashboard.clerk.com/~/user-authentication/sso-connections/enterprise), and select the organization. Users from that organization's email domain then authenticate through it automatically with `strategy: 'enterprise_sso'`.

No per-IdP pool surgery, no destructive [full-replace](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_UpdateUserPoolClient.html), no serialization lock.

In this second part, we compared the enterprise capabilities of Clerk and AWS Cognito, showing how Clerk bundles features like B2B multi-tenancy and Directory Sync, whereas Cognito requires you to assemble them. In [Part 3](https://clerk.com/articles/clerk-vs-aws-cognito-developer-experience-vs-scale-economics-3.md), we will break down scale economics, the cost of ownership, and how to handle vendor lock-in and migrations.

## Frequently asked questions

### Does AWS Cognito support B2B multi-tenancy?

Cognito does not have a native organization or tenant primitive. Teams emulate multi-tenancy using patterns like a pool-per-tenant, app-client-per-tenant, group-based isolation, or custom attributes, each of which carries trade-offs in isolation and scale.

### How do I sync AWS Cognito users to my database?

Cognito offers synchronous Lambda triggers and EventBridge coverage via CloudTrail, but it lacks a native, durable webhook for every directory mutation. Out-of-band attribute updates may not fire a trigger, so keeping a database in sync often requires custom serverless architecture.

### Does Clerk support SCIM provisioning?

Yes. Clerk offers Directory Sync (SCIM) as a generally available feature bundled with each enterprise connection. Deprovisioning a user through SCIM immediately revokes their sessions and fires a standard `user.updated` webhook.

## In this series

1. [Clerk vs AWS Cognito: Developer Experience vs Scale Economics](https://clerk.com/articles/clerk-vs-aws-cognito-developer-experience-vs-scale-economics.md)
2. **Clerk vs AWS Cognito: Developer Experience vs Scale Economics - Part 2** (you are here)
3. [Clerk vs AWS Cognito: Developer Experience vs Scale Economics - Part 3](https://clerk.com/articles/clerk-vs-aws-cognito-developer-experience-vs-scale-economics-3.md)
