Rate limits overview

Stytch enforces rate limits across our API endpoints for a few reasons:

  1. To protect our infrastructure and offer the best reliability possible
    • As an example, an unintentional bug in a customer's code that calls our Create User endpoint many times within a short period could affect our own infrastructure as well as result in unintended user states.
  2. To limit the surface area for common attack vectors from bad actors
    • For instance, we have baseline rate limiting in place for our endpoints that trigger an SMS OTP code to be sent to offer a first line of defense against toll fraud attacks.
  3. To satisfy security requirements

Rate limit enforcement depends on a number of factors - this resource will describe the general axes used to determine and enforce rate limits and what to expect when building with Stytch.

How rate limits work at Stytch

Rate limits at Stytch have three key components that determine rate limit enforcement:

  1. Field: The unique field or identifier that is used to determine rate limits - for instance a specific email address or a Stytch user_id. These range in scope - for instance, Stytch rate limits the number of SMS OTP Send calls on phone number and phone number prefix (e.g. country code), but the number of Create User requests on the Stytch project_id.

  2. Interval: The period of time over which this rate limit is assessed, e.g. second, minute, hour, day. Once a rate limit is hit, the relevant time interval will need to pass before the user is allowed to try again. Note that intervals are not rolling, but are top of the hour.

  3. Endpoint: The Stytch API endpoint(s) that the rate limit is assessed on. Some of our rate limits aggregate on more than one endpoint - for instance, we restrict Email Magic Link’s Send, Login or Create, and Invite endpoints to one request per second per email across all three endpoints to avoid collisions, as they all initiate an email sent to the end user.

Example scenario

Stytch rate limits Password Authenticate calls to help prevent credential stuffing attacks and to keep our infrastructure safe. Our current rate limit for our Password Authenticate endpoint is 10/hour/email address.

If 10 Password Authenticate calls are made in an hour, the 11th will return a 429 error. Once the hour changes, at the top of the next hour Password Authenticate calls using that email address will no longer run into rate limits.

If a user who is hitting the Password Authenticate rate limit successfully resets their password, the rate limit will be cleared.

Building for rate limits

We designed our rate limits at Stytch such that legitimate user traffic shouldn’t result in rate limiting, but it’s important to keep them in mind when building out user flows to avoid patterns that could result in rate limiting.

Once a rate limit threshold has been reached, it generally cannot be reset or changed for the particular field or user that was rate limited, so it’s important to keep a few things in mind when building with Stytch to avoid unwanted rate limit breaches.

UI Considerations

Whenever possible, we recommend building rate limit protections into your application’s UI.

For instance, if you utilize our Email OTP authentication flow, we generally recommend baking in a reset timer, preventing users from initiating many Email OTP codes in short succession.

Below is an example code snippet showing a exponential cooldown timer for a button that sends an OTP code:

const handleOTPClick = () => {
    // Disable the button when it's clicked
    setOTPButtonDisabled(true);

    // Calculate the exponential backoff time based on the retry count
    const backoffTime = Math.pow(2, retryCount) * 30000; // In milliseconds

    // Increment the retry count
    setRetryCount(retryCount + 1);

    // Enable the button after the calculated backoff time
    setTimeout(() => {
      setButtonDisabled(false);
    }, backoffTime);
  };

Testing and debugging flows

Our rate limits at Stytch are designed such that normal user traffic should generally not run into rate limits in our Live environment. Our Test environment is built to support iteration and testing, and has different rate limits than our Live environment.

Building out testing flows in our Test environment rather than our Live environment can help to avoid running into rate limits.

For instance, if you’re writing end to end tests which will involve authenticating many times in a row to test various application flows, we recommend doing so in our Test environment rather than Live.

Authentication flow design

Utilizing more than one primary auth factor in your authentication flow can offer a fallback authentication option in case one primary factor is unavailable, either due to rate limits (e.g. repeated password authentication attempts) or any other reason.

Fallback authentication methods should generally offer a mix of different products entirely (e.g. SMS OTP and Email Magic Links), and/or different delivery methods (e.g. SMS and Email OTP). Doing so is protective against not just rate limits, but also the loss of a device or temporary inaccessibility.

For instance, if an SMS OTP is failing to deliver because the phone is currently out of its service coverage area, offering an alternative method of delivery, such Email or WhatsApp OTP, or an alternative authentication factor, such as Passwords, can help avoid a situation where a user makes many successive calls to send an SMS OTP because it is the only authentication method available.

Handling unexpected 429 errors

If you notice or receive reports of 429 errors, a good place to start is the Event logs section of your Stytch Dashboard to investigate and gather context.

Event logs can show the series of events that led up to a 429 error, which can be helpful in determining mitigation strategies to prevent future occurrences.

We don’t return detailed information about the specific rate limit hit in our 429 too_many_requests error response, but if you receive this error unexpectedly and during a legitimate user flow, feel free to reach out to support@stytch.com for more information on why the rate limit was enforced.