'; user_status_content.firstChild.appendChild(avatarContainer); } else { // Placeholder for LoggedOutUserMenu let loggedOutContainer = document.createElement('div'); // if LoggedOutUserMenu fallback let userBtn = document.createElement('button'); userBtn.style.width = "33px"; userBtn.style.height = "33px"; userBtn.style.display = "flex"; userBtn.style.alignItems = "center"; userBtn.style.justifyContent = "center"; userBtn.style.color = "var(--ds-gray-900)"; userBtn.style.border = "1px solid var(--ds-gray-300)"; userBtn.style.borderRadius = "100%"; userBtn.style.cursor = "pointer"; userBtn.style.background = "transparent"; userBtn.style.padding = "0"; // user icon ( from geist) let svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg'); svg.setAttribute('data-testid', 'geist-icon'); svg.setAttribute('height', '16'); svg.setAttribute('stroke-linejoin', 'round'); svg.setAttribute('style', 'color:currentColor'); svg.setAttribute('viewBox', '0 0 16 16'); svg.setAttribute('width', '16'); let path = document.createElementNS('http://www.w3.org/2000/svg', 'path'); path.setAttribute('fill-rule', 'evenodd'); path.setAttribute('clip-rule', 'evenodd'); path.setAttribute('d', 'M7.75 0C5.95507 0 4.5 1.45507 4.5 3.25V3.75C4.5 5.54493 5.95507 7 7.75 7H8.25C10.0449 7 11.5 5.54493 11.5 3.75V3.25C11.5 1.45507 10.0449 0 8.25 0H7.75ZM6 3.25C6 2.2835 6.7835 1.5 7.75 1.5H8.25C9.2165 1.5 10 2.2835 10 3.25V3.75C10 4.7165 9.2165 5.5 8.25 5.5H7.75C6.7835 5.5 6 4.7165 6 3.75V3.25ZM2.5 14.5V13.1709C3.31958 11.5377 4.99308 10.5 6.82945 10.5H9.17055C11.0069 10.5 12.6804 11.5377 13.5 13.1709V14.5H2.5ZM6.82945 9C4.35483 9 2.10604 10.4388 1.06903 12.6857L1 12.8353V13V15.25V16H1.75H14.25H15V15.25V13V12.8353L14.931 12.6857C13.894 10.4388 11.6452 9 9.17055 9H6.82945Z'); path.setAttribute('fill', 'currentColor'); svg.appendChild(path); userBtn.appendChild(svg); loggedOutContainer.appendChild(userBtn); loggedOutContainer.style.display = 'flex'; loggedOutContainer.style.gap = '8px'; loggedOutContainer.style.alignItems = 'center'; user_status_content.firstChild.appendChild(loggedOutContainer); } })();
Menu

Rate Limiting SDK

Last updated September 24, 2025

You can configure a custom rule with rate limit in your code by using the @vercel/firewall package. This can be useful in the following cases:

  • You need to set a rate limit on requests in your backend
  • You want to use additional conditions with the rate limit that are not possible in the custom rule configuration of the dashboard
    1. From your dashboard, select the project that you'd like to configure rate limiting for. Then select the Firewall tab
    2. Select Configure on the top right of the Firewall overview page. Then, select + New Rule
    3. Complete the fields for the rule as follows
      1. Type a name such as "Firewall api rule"
      2. In the Configure section, for the first If condition, select @vercel/firewall
      3. Use update-object as the Rate limit ID
      4. Use the default values for Rate Limit and Then
    4. Select Save Rule
    5. Apply the changes:
      • When you make any change, you will see a Review Changes button appear or update on the top right with the number of changes requested
      • Select Review Changes and review the changes to be applied
      • Select Publish to apply the changes to your production deployment
  1. You can now use the Rate limit ID update-object set up above with @vercel/firewall to rate limit any request based on your own conditions. In the example below, you rate limit a request based on its IP.

    rate-limit.ts
    import { checkRateLimit } from '@vercel/firewall';
     
    export async function POST(request: Request) {
      const { rateLimited } = await checkRateLimit('update-object', { request });
      if (rateLimited) {
        return new Response(
          JSON.stringify({
            error: 'Rate limit exceeded',
          }),
          {
            status: 429,
            headers: {
              'Content-Type': 'application/json',
            },
          },
        );
      }
      // Otherwise, continue with other tasks
    }
  2. For your code to run when deployed in a preview deployment, you need to:

For example, you can include an additional filter for a request header and check whether this header matches a key from the user's authentication, to apply the rate limit. This filter is not possible in the custom rule dashboard.

Edit the custom rule in the dashboard and add an If condition with the following values, and click Save Rule:

  • Filter dropdown: #Request Header
  • Value: xrr-internal-header
  • Operator: Equals
  • Match value: internal

Use the following code to apply the rate limit only to users of the organization.

rate-limit.ts
import { checkRateLimit } from '@vercel/firewall';
import { authenticateUser } from './auth';
 
export async function POST(request: Request) {
  const auth = await authenticateUser(request);
  const { rateLimited } = await checkRateLimit('update-object', {
    request,
    rateLimitKey: auth.orgId,
  });
  if (rateLimited) {
    return new Response(
      JSON.stringify({
        error: 'Rate limit exceeded',
      }),
      {
        status: 429,
        headers: {
          'Content-Type': 'application/json',
        },
      },
    );
  }
}

Was this helpful?

supported.