Skip to main content

Clerk Changelog

Infra Changelog - Sep 25, 2025

Category
Infra
Published

Isolated compute for session API, database tuning, and more

Starting with this post, we will regularly share details about ongoing infrastructure improvements. These updates happen continually behind the scenes, and will not impact end-users beyond improving reliability and performance.

Released this week

Isolated compute for our Session API

Following the incident on June 26, we began isolating our session API infrastructure from the rest of our frontend-facing API, which includes workloads like sign ups, sign ins, user profiles.

To keep our session API running during an incident, we require access to session-relevant storage and compute during that downtime.

We started with storage, which was the more challenging of the two workstreams. Thankfully, this was released ahead of the incident last week, and helped reduce the blast radius.

When queries against our primary database failed, our new “outage resiliency” mechanism kicked in and started working off a read replica to serve session tokens instead. Here’s a chart of the tokens served:

Outage resilience spike

Unfortunately, this chart does not reflect the full volume of session tokens that were requested during the incident, since many failed because our compute was exhausted. Here’s what happened:

  • Clerk uses Google Cloud Run with auto-scaling for compute. It serves all requests for sessions, sign ups, sign ins, organizations, and billing.
  • When the database failed, session requests continued to succeed because of our failover mechanism, but non-session requests got stuck behind query timeouts, and overall request latency increased.
  • Increased request latency triggered auto-scaling of Cloud Run until the configured maximum containers was hit. During this autoscaling, the session requests continued to succeed.
  • Once the maximum was hit, throughput for our frontend API Cloud Run service dropped sharply, and session requests were no longer reliably being served.

The solution to this is to serve session requests from a separate Cloud Run service than the rest of our frontend API. That way, session requests can retain high throughput against the read replica during a primary database incident, while the rest of the of the frontend API can wait for the primary database to recover.

We’ve built this so our session API compute is always on and handling all session requests, so we do not need to wait for a failover of Cloud Run. Here are charts showing our request volume move to the new Cloud Run service for our session API after release:

Frontend API requests - now with session requests removed:

Frontend API decrease

Session API requests running independently:

Session API start

Database tuning

Following the auto-upgrade last week, it was expected that we’d need to retune our database in response to its improved overall performance. Below is the improvement to average query latency after a process of reindexing and adjusting our auto-vacuum settings:

September 18: First full stable day

  • P50: 40μs
  • P95: 115μs
  • P99: 703μs

September 24: Yesterday

  • P50: 40μs (no change)
  • P95: 96μs (16% improvement)
  • P99: 584μs (17% improvement)

In progress

Reducing latency between our compute and our database

Working with GCP support, we learned that there is an opportunity to reduce the network latency between Cloud Run and Cloud SQL, to improve our overall request latency. We expect this to be completed within the next week.

Continued database tuning

We have more database tuning ahead. We expect modest additional improvements as we continue to monitor auto-vacuum settings, and begin adjusting fillfactor settings.

Planned

Where possible, convert high-write workloads from update to append-only

Our original architecture depended on frequent updates, which has become burdensome on our database as we’ve scaled.

Where possible, we plan to reduce our use of this pattern, and instead rely on append-only tables. In the process, we may opt to move these workloads to a time-series database like ClickHouse.

Reduce session API requests

We’ve discovered a bug in our session refresh logic that causes individual devices to send more refreshes than necessary. We believe resolving this bug can significantly reduce our request volume.

Further session API isolation

Currently, the session API must failover to a replica during primary database downtime, which is not ideal since the primary database is still impacted by other workloads. We are pursuing solutions that would lead to a session-specific database.

Additional service isolation

While working to isolate our Session API, we’ve already developed a handful of techniques that can be re-used to isolate other services. When done, we’d like isolated workloads for each of our product areas:

  • Session
  • Sign up
  • Sign in
  • User account management (profile fields)
  • Organizations
  • Billing
  • Fraud

Database restart resilience

Over the last few years, one of the benefits of Cloud SQL has been that it can achieve most database upgrades with only a few seconds of downtime. Clerk has application logic to ensure that requests in these few seconds are retried and unnoticeable to users.

But now, Clerk is rapidly approaching the point where we need to execute operations that require longer primary database downtime. We require additional application logic to handle writes during this downtime without impacting users.

Database connection pooler and major version upgrade

Clerk has historically only used a client-side database pooler inside our Cloud Run containers. Though we’ve known this is non-optimal, we did this because Google did not offer a managed database connection pooler, and we were skeptical of putting a self-hosted service in between two managed services (Cloud Run and Cloud SQL).

In March, Google released a managed connection pooler in Preview, and it reached General Availability this week. However, using the connection pooler will require a major database version upgrade, and in our particular case, a network infrastructure upgrade. We are collaborating with Google to determine how we can achieve both upgrades safely and without downtime.

Simultaneously, we are investigating other database and connection pooler solutions that can run within our VPC.

Contributor
Colin Sidoti

Share this article

SAML ForceAuthn

Category
SAML
Published

Clerk now supports configuring the ForceAuthn parameter on SAML authentication requests.

For users with SAML integrations, the Clerk dashboard now supports configuring the ForceAuthn on a per-connection basis.

This is especially important on shared or multi-user devices where a previous user may still have an active SSO session at the Identity Provider (IdP). When ForceAuthn is enabled, Clerk includes the ForceAuthn=true parameter on the SAML AuthnRequest so the IdP will ignore any existing SSO session and require the user to re‑authenticate (password, MFA, etc.). This prevents the next person on the same machine from silently inheriting access due to someone else’s logged-in IdP session.

Expectations

Existing SAML connections are unchanged—ForceAuthn remains off by default to preserve current sign‑in behavior. If you enable it, users will be prompted to re‑authenticate at the IdP on every SSO sign‑in for that connection.

How to enable

In the Clerk Dashboard, navigate to the SSO Connections page

  1. Select your SAML connection
  2. Select the Advanced tab
  3. Enable Force authentication
  4. Save
Contributor
Kevin Wang

Share this article

Last-used sign-in method badge

Category
Product
Published

Users can now easily identify their last-used sign-in method with a visual badge indicator.

The sign-in experience now includes a helpful badge that displays on the last-used sign-in method, making it easier for users to quickly identify and select their previously used authentication option.

The badge appears automatically based on the user's sign-in history and requires no additional configuration from developers on new applications.

Existing applications can opt-in to this feature for their instances via the Clerk Dashboard.

Contributors
Tom Milewski
George Vanjek

Share this article

Android SDK General Availability

Category
Android
Published

The Clerk Android SDK has reached general availability, delivering production-ready authentication and user management for native Android applications.

Today marks a significant milestone in our commitment to providing exceptional authentication experiences across all platforms. After a successful beta, we're thrilled to announce that the Clerk Android SDK is now generally available! The Clerk Android SDK addresses the need for first-class native authentication head-on. Built from the ground up with Kotlin and following Android's latest development standards, it provides the robust, idiomatic experience that Android developers expect while maintaining the simplicity and power that define all Clerk products. Let's explore what makes this release special.

Organization support

A new feature in this release is organization support. This allows you to create and manage organizations within your Android application.

scope.launch {
  Organization.create(name = "My Organization")
        .onSuccess { organization ->
          // Organization created successfully
        }
        .onError { error ->
          // Error creating organization
        }
}

Jetpack Compose

The Clerk Android SDK was built with Jetpack Compose in mind, allowing you to harness its declarative approach to user interfaces on all Android platforms.

MainActivity.kt
@Composable
fun MainActivity() {
  Column {
    if(Clerk.user != null) {
      Text("Hello, ${Clerk.user.id}")
    } else {
      Text("You are signed out")
    }
  }
}

Coroutines

The Clerk Android SDK makes use of the latest in coroutines, allowing your code to be as readable and expressive as possible.

// Create a new sign up
scope.launch {
  val signUp = SignUp.create(SignUp.CreateParams.Standard(emailAddress = "newuser@clerk.com", password = "••••••••••"))

  // Send an email with a one time code
  // to verify the user's email
  signUp.prepareVerification(SignUp.PrepareVerificationParams.EmailCode)
}

Social Connections (OAuth)

Authenticate with your favorite social providers in just a few lines of code.

scope.launch {
  SignIn.authenticateWithRedirect(SignIn.AuthenticateWithRedirectParams.OAuth(provider = OAuthProvider.GOOGLE))
}

Session Management

Let the Clerk Android SDK take care of managing your user's authentication state so you can get back to building your app.

MainActivity.kt
@Composable
fun MainActivity() {
  Column {
    if(Clerk.session != null) {
      Text(Clerk.session.id)
    } else {
      Text("No session")
    }
  }

Migration from Beta

For existing beta users, simply update your SDK version to 0.1.10 to access all GA features and improvements.

Getting Started

Ready to integrate production-ready authentication into your Android app? Check out our comprehensive resources:

Looking Forward

The general availability of our Android SDK represents more than just a product milestone - it demonstrates our ongoing commitment to providing world-class authentication solutions across every platform where your users engage with your applications.

We're incredibly grateful to our beta community whose feedback was instrumental in shaping this release. As we continue expanding platform support and adding new authentication capabilities, the Android SDK will evolve alongside our broader ecosystem. Expect regular updates with new features, performance improvements, and expanded integration options.

Have questions about the GA release, or need help with migration or implementation? Our support team is ready to help, and our Discord community is more active than ever with developers sharing experiences and best practices.

The full SDK source code remains available on GitHub, where you can contribute, report issues, or simply explore how we've built this authentication solution for the Android ecosystem.

Contributor
Sam Wolfand

Share this article

Fetch user subscription

Category
Billing
Published

Fetch a user's subscription from the Backend API

Developers can now fetch a user's subscription directly from our Backend API via GET /user/:user_id/billing/subscription.

Usage with Next.js

import { clerkClient, auth } from '@clerk/nextjs/server'

export async function getUserSubscription() {
  const { userId } = await auth.protect()
  const client = await clerkClient()
  return client.billing.getUserBillingSubscription(userId)
}

For more information and SDK availability, check out the documentation.

Contributors
Maurício Antunes
Pantelis Eleftheriadis

Share this article

Free trials for subscriptions

Category
Billing
Published

The easiest way to not charge your customers.

Free trials are a great way to get your users to their "a-ha!" moment and increase conversions, and Clerk Billing makes them easy to setup and use.

Straightforward Configuration

Enable free trials for any plan in the Clerk Dashboard and choose the duration of the trial. Or you can roll out the same free trials configuration for many plans at once.

Existing users will see no change to their subscriptions, but any new signups will get your configured free trial before their card is charged. Change your configuration at any time, and it will take effect for any new signups after that point.

Easy to Manage

You can cancel your users' free trials at any point from the Clerk Dashboard, or opt to have their subscription end when the free trial ends. You can also extend the free trial of any user at any time during their trial.

Best Practices Built-In

Free trials automatically use industry best practices without any configuration. Users will be required to enter a credit card before starting their trial, mitigating abuse and ensuring when their trial ends they transition smoothly to a paid subscription. And users that have already paid you or already had a free trial are ineligible to start a new one.

Get Started Today

Ready to increase your conversions? Get started with free trials:

We're working to make Clerk Billing the best way to charge (and not charge) your users. Have any questions or suggestions? Reach out through our feedback portal or join the discussion in our Discord community.

Contributor
Clerk

Share this article