Back to all articles
API Rate Limiting

Supa-dynamic rate-limiting based on data (using supabase)

Josh Twist
·
December 5, 2022
·
1 min read

In this video, you'll learn how to make rate-limiting extraordinarily dynamic by making the rate-limiter interact with external services like Supabase & Xata

December 5, 2022

One of the best things about Zuplo is it's programmable nature. That combined with our approach to making policies composable means you can do some amazing things with them, like our rate-limiter. In this video we show how you can have the rate-limiter interact with external services and data. Here we use supabase as a data-source for the limits.

Here's the key code from the sample

TypeScriptts
import {
  ZuploContext,
  ZuploRequest,
  ZoneCache,
  CustomRateLimitDetails,
} from "@zuplo/runtime";
import { createClient } from "@supabase/supabase-js";

const fallBackLimits = {
  requestsAllowed: 10000,
  timeWindowMinutes: 1,
};

const CACHE_NAME = "rate-limit-cache";
const CACHE_KEY = "rate-limit-data";

export async function getRateLimit(
  request: ZuploRequest,
  context: ZuploContext,
  policyName: string,
) {
  const limitResponse: CustomRateLimitDetails = {
    key: request.user.sub,
    ...fallBackLimits,
  };

  const userGroup = request.user.data.rateLimitGroup;
  const cache = new ZoneCache(CACHE_NAME, context);

  const cached: any = await cache.get(CACHE_KEY);

  if (cached) {
    context.log.debug("cache hit");
    const item = cached.find((row) => row.userGroup === userGroup);
    limitResponse.requestsAllowed = item.reqPerMinute;
    return limitResponse;
  }

  context.log.debug("cache miss");
  const supabase = createClient(
    "https://YOUR_SUPABASE_URL.supabase.co",
    "YOUR_SUPABASE_TOKEN",
  );
  const { data, error } = await supabase.from("rate-limits").select();

  if (error) {
    context.log.error(`Error reading data from supabase`, error);
    // return fallback rate-limit - don't want API downtime
    // if this dependency is down.
    return limitResponse;
  }

  const item = data.find((row) => row.userGroup === userGroup);

  if (!item) {
    context.log.warn(`No row rateLimitId '${userGroup}' found, using fallback`);
    // return fallback
    return limitResponse;
  }

  void cache.put(CACHE_KEY, data, 10);

  limitResponse.requestsAllowed = item.reqPerMinute;
  return limitResponse;
}

You could make this even higher performance by having the cache have a longer expiry, but periodically reloading the data from supabase asynchronously and pushing the results back into the cache; something like an SWR (stale, while revalidate) approach.

Get started with Zuplo for free today: Sign Up Free

See also:

Shipping a public API backed by Supabase

API Authentication using Supabase JWT tokens

Related Articles

Continue reading from the Zuplo blog.

API Monetization 101

API Monetization 101: Your Guide to Charging for Your API

A three-part series on API monetization: what to count, how to structure plans, and how to decide what to charge. Start here for the full picture.

4 min read
API Monetization 101

Use AI to Plan Your API Pricing Strategy

Get clear tiers, a comparison table, and reasoning so you can price your API with confidence and move on to implementation faster.

3 min read

Scale your APIs with
confidence.

Start for free or book a demo with our team.
Book a demoStart for Free
SOC 2 TYPE 2High Performer Spring 2025Momentum Leader Spring 2025Best Estimated ROI Spring 2025Easiest To Use Spring 2025Fastest Implementation Spring 2025

Get Updates From Zuplo

Zuplo logo
© 2026 zuplo. All rights reserved.
Products & Features
API ManagementAI GatewayMCP ServersMCP GatewayDeveloper PortalRate LimitingOpenAPI NativeGitOpsProgrammableAPI Key ManagementMulti-cloudAPI GovernanceMonetizationSelf-Serve DevX
Developers
DocumentationBlogLearning CenterCommunityChangelogIntegrations
Product
PricingSupportSign InCustomer Stories
Company
About UsMedia KitCareersStatusTrust & Compliance
Privacy PolicySecurity PoliciesTerms of ServiceTrust & Compliance
Docs
Pricing
Sign Up
Login
ContactBook a demoFAQ
Zuplo logo
DocsPricingSign Up
Login