·5 min read

Protecting my wallet by ratelimiting OpenAI requests

Pau KraftPau KraftSoftware Engineer @TeampilotAI (Guest Author)

Coming up with ideas for a project or a company is one thing, but finding a good name for it can be challenging. More than once, I found myself with a project but without a cool name to launch it. So, I created brandix.ai, a free tool that helps generate unique names for your projects or companies. Unlike other online AI name generators, you can chat with the generator and modify the generations based on that. For example, you can provide a description of what your project does, and it will generate different ideas based on that.

Let's delve into how Brandix works and how Upstash can potentially save my credit card from being maxed out.

How it works

Name generation

To be honest, it's quite simple. All the magic behind Brandix comes from the hard work of OpenAI's GPT models. That's the stuff that powers Brandix.

To keep costs at a minimum and with tests showing that GPT-4 doesn't have any advantages for this specific use case, I chose GPT-3.5 to generate the names.

You can imagine the generate page as a chat between you and the AI. You send a message or ask for more versions, and the AI responds with those.

If you send a request (either by sending a message or requesting more names), the backend adds a pre-prompt to instruct the AI to answer with five brand names in a list, and sends it to OpenAI.

GPT-3.5 is sometimes a bit too polite and starts its response with something like "Sure, I can provide you with some names:", that's why we instruct GPT to return a numbered list. We then split the string line by line and filter out all strings, with the help of a RegEx (/^[0-9]/), that don't start with a number.

The result looks something like this:

1. StellarEdge
2. CosmoTech
3. AstroNova
4. GalactiCorp
5. CelestialX

The problem is, it gets streamed in token by token, so we can't just split it line by line and call it a day. But don't worry, it's still quite simple. We just split it and don't use the last item of the array.

For example, let's imagine our current streamed string is:

1. StellarEdge
2. CosmoTech
3. As

Now we split it line by line so we get an array like this

["1. StellarEdge", "2. CosmoTech", "3. As"]

Do you see it? All elements of the array but the last are complete, so we just leave the last one behind and only use the elements before. (If the stream is done we do use the last one, because then we know that it's complete)

Now we throw a little RegEx at it (/^\d+.\s/) that replaces the unwanted number in front.

The current array looks like this:

["StellarEdge", "CosmoTech"]

And now we just check if we have the domain already in our list and if not we add it and start the domain availability check.

That's it.

Domain availability check

This is quite an unusual one. Since the service is free to use, I have to pay for everything. So, I didn't want to go the easy way and throw money at an API and call it a day.

So, how am I doing it, then?

It is a process consisting of two stages.

First, we make a DNS lookup to see if there is an IP behind the domain. If there is, the domain is already in use.

If there isn't, the domain could still be registered but not in use. So, we ask a WHOIS Database if the domain is registered.

Now we can be pretty sure that the domain is available or not.

Sidenote: yes, we could skip the DNS part and only ask the WHOIS DB, but the DB is a free service, and we don't want to spam them with endless requests, so we first check if the domain is taken with a more resource-efficient approach.

But how does Upstash fit in?

As I explained earlier, the service is free to use, and I pay for it. To protect myself from bankruptcy, I need to build in some sort of rate limit.

And that's where Upstash and the ratelimit library come in.

You create a Redis on Upstash.

And initiate the ratelimiter, with the algorithm you want:

const ratelimit = new Ratelimit({
  redis: Redis.fromEnv(),
  limiter: Ratelimit.fixedWindow(10, "10 s"),
  analytics: true
});

and then check if a user (based on their IP) has made too many requests:

const { success } = await ratelimit.limit(REQUEST-IP)

If success is true we let the request through, if it's false we return a 429, informing the user that they please shouldn't empty my bank account.

Wrapping things up

Thanks for reading. Brandix is a fun little side project I made in a few days. But with tools like Next.js, Vercel, OpenAI, Tailwind, Shadcn UI and Upstash Redis, it's incredibly simple to bring small, but still production-ready projects to life. If you have any questions or feedback, feel free to reach out to me on Twitter.

Relevant links: