馃敟 LIMITAR LA FREQUENCIA DE PETICIONES UTILIZANDO UPSTASH

驴Qu茅 es el rate limit (frequencia de peticiones)?

El rate limit en las APIs es una medida de control crucial para mantener la estabilidad y equidad en el uso de servicios en l铆nea. Funciona como un mecanismo de restricci贸n que limita el n煤mero de solicitudes que un usuario o aplicaci贸n puede realizar en un per铆odo de tiempo determinado. Esto evita la sobrecarga del servidor y previene abusos, como ataques de fuerza bruta o scraping excesivo de datos.

Los rate limits se expresan generalmente como un n煤mero m谩ximo de solicitudes permitidas en un lapso espec铆fico, como 1000 solicitudes por hora. Una vez alcanzado este l铆mite, la API puede rechazar temporalmente las solicitudes adicionales o responder con un c贸digo de error. Los desarrolladores deben estar atentos a estos l铆mites al dise帽ar sus aplicaciones para garantizar un uso responsable y eficiente de los recursos de la API.

Upstash

Upstash es un servicio serverless que permite utilizar soluciones como Redis y Kafka en la nube.

  1. Para definir nuestro rate limit, vamos a crear una cuenta primero en upstash.com si es que no tenemos una.

  2. Creamos una nueva base de datos regional en la locaci贸n mas cercana a donde nuestro proyecto se encuentra localizado.

  3. Mientras la base de datos se crea, instalamos el paquete upstash ratelimiter.

    pnpm add @upstash/ratelimit
    
  4. El driver que vamos a utilizar es el de Redis, as铆 que instalamos el paquete.

    pnpm add @upstash/redis
    
  5. En Upstash vamos la secci贸n Rest API > .env y copiamos las variables de entorno, las pegamos dentro de nuestro archivo .env y dentro de las variables de entorno de vercel.

    UPSTASH_REDIS_REST_URL="https://....."
    UPSTASH_REDIS_REST_TOKEN=".............................."
    
  6. Creamos la configuraci贸n para nuestro rate limiter dentro del router de posts.

    import { Ratelimit } from '@upstash/ratelimit'
    import { Redis } from '@upstash/redis'
    import { z } from 'zod'
    // ...
    
    const rateLimiter = new Ratelimit({
        redis: Redis.fromEnv(),
        limiter: Ratelimit.slidingWindow(3, '1 m'),
        analytics: true,
    })
    
  7. Actualizamos el posts:create para agregando un l铆mite basado en el id del autor.

    export const postsRouter = createTRPCRouter({
        // ....
        create: privateProcedure
            .input(
                z.object({
                    content: z.string().emoji().min(1).max(280),
                })
            )
            .mutation(async ({ ctx, input }) => {
                const authorId = ctx.userId
    
                const { success } = await rateLimiter.limit(authorId)
    
                if (!success) {
                    throw new TRPCError({ code: 'TOO_MANY_REQUESTS' })
                }
    
                await ctx.prisma.post.create({
                    data: {
                        content: input.content,
                        authorId,
                    },
                })
            }),
    })
    
  8. Probamos nuevamente intentando enviar posts de manera repetida, hasta que veamos que trpc responde con el mensaje.

    client.js:1 TRPCClientError: TOO_MANY_REQUESTS
    at TRPCClientError.from (TRPCClientError-fef6cf44.mjs:10:1)
    at eval (httpBatchLink-fbd7b43c.mjs:189:44)
    
  9. Si vamos a Upstash dentro de la secci贸n Usage, empezaremos a ver el consumo que se esta realizando de Redis, como forma de limitar las peticiones frecuentes.

Hemos podido restringir el n煤mero de peticiones recurrentes utilizando una base de datos Redis en [Upstash][https://upstash.com] y el paquete @upstash/ratelimit para dicho prop贸sito.