Back to Blog
Guide7 min read2026-05-01

API Rate Limiting with Edge Functions on PandaStack

Protect your API from abuse without adding latency. Use PandaStack Edge Functions (powered by OpenWhisk) to implement rate limiting close to your users.

# API Rate Limiting with Edge Functions on PandaStack

An unprotected API is an invitation for abuse: scrapers, brute-force attacks, and accidental infinite loops from buggy clients can take your service down or run up your database costs. Rate limiting is the first line of defense — and implementing it at the edge means requests are blocked before they ever reach your application servers.

PandaStack Edge Functions run on Apache OpenWhisk and support Node.js and Python runtimes. Here is how to implement a rate limiter using Edge Functions and a managed Redis instance.

1. Why Rate Limit at the Edge?

Rate limiting at the application level works but has a cost: every request — even ones you are going to reject — hits your application server, consumes a database connection, and runs your middleware stack. High-volume abuse attacks can overwhelm your servers before the rate limiter even has a chance to block them.

Edge functions run before traffic reaches your application. Blocked requests never touch your backend.

2. Architecture Overview

User Request
     ↓
PandaStack Edge Function (rate limiter)
     ↓ (if allowed)
Your Application Container
     ↓
Managed Database / Services

The edge function checks a Redis counter per IP address (or API key). If the counter exceeds the limit, it returns 429 immediately. If not, it increments the counter and forwards the request.

3. Create a Managed Redis Database

  1. 1Log in to [dashboard.pandastack.io](https://dashboard.pandastack.io)
  2. 2Go to DatabasesNew DatabaseRedis
  3. 3Copy the connection URL

Your Redis URL will be in the format: redis://username:password@host:6379

4. Write the Rate Limiter Edge Function (Node.js)

Create a new file rate-limiter.js:

const redis = require('redis')

let client

async function getRedisClient() {
    if (!client) {
        client = redis.createClient({ url: process.env.REDIS_URL })
        await client.connect()
    }
    return client
}

const WINDOW_SECONDS = 60       // 1 minute window
const MAX_REQUESTS = 100        // 100 requests per minute

async function main(params) {
    const ip = params.__ow_headers['x-forwarded-for'] || 'unknown'
    const key = `rate:${ip}`

    const redis = await getRedisClient()

    // Increment counter with expiry
    const count = await redis.incr(key)
    if (count === 1) {
        await redis.expire(key, WINDOW_SECONDS)
    }

    if (count > MAX_REQUESTS) {
        return {
            statusCode: 429,
            headers: {
                'Content-Type': 'application/json',
                'Retry-After': String(WINDOW_SECONDS),
                'X-RateLimit-Limit': String(MAX_REQUESTS),
                'X-RateLimit-Remaining': '0',
            },
            body: JSON.stringify({
                error: 'Too Many Requests',
                message: `Rate limit exceeded. Try again in ${WINDOW_SECONDS} seconds.`,
            }),
        }
    }

    // Forward to your application (return a pass-through response)
    return {
        statusCode: 200,
        headers: {
            'X-RateLimit-Limit': String(MAX_REQUESTS),
            'X-RateLimit-Remaining': String(Math.max(0, MAX_REQUESTS - count)),
        },
        body: JSON.stringify({ allowed: true }),
    }
}

module.exports.main = main

5. Deploy the Edge Function

  1. 1Dashboard → Edge FunctionsNew Function
  2. 2Connect your GitHub repository containing rate-limiter.js
  3. 3Select Node.js runtime
  4. 4Set environment variables:

- REDIS_URL: Your managed Redis connection URL

  1. 1Click Deploy

6. Set Different Limits by Client Tier

For APIs with tiered access (free vs. paid), use API keys to set per-tier limits:

const TIERS = {
    free: 60,       // 60 req/min
    basic: 300,     // 300 req/min
    premium: 1000,  // 1000 req/min
}

async function main(params) {
    const apiKey = params.__ow_headers['x-api-key'] || 'anonymous'
    const tier = await getTier(apiKey)  // lookup from Redis or your DB
    const limit = TIERS[tier] || TIERS.free
    // ... rest of rate limiting logic using limit
}

7. Monitor Edge Function Invocations

PandaStack's edge function dashboard shows:

  • Total invocations per day
  • Error rates
  • Average execution time
  • Rejected requests (useful for tracking abuse volume)

Go to Edge Functions → select your function → Analytics.

8. Adjust Limits Based on Observed Traffic

Start conservative (100 req/min per IP) and adjust based on your analytics:

  • If legitimate users are being rate limited, increase the limit
  • If you are seeing abuse patterns, decrease the limit or add IP blocking
  • Add exemptions for known IP ranges (your own monitoring services, partner integrations)

Full docs: [docs.pandastack.io](https://docs.pandastack.io).

Ready to deploy?

Start free on PandaStack — no credit card required.

Start free on PandaStack

More in Guide

Browse all Guide articles →

See also