<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Unkey</title>
    <description>The latest articles on DEV Community by Unkey (@unkey).</description>
    <link>https://dev.to/unkey</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Forganization%2Fprofile_image%2F9070%2F28dd6c4a-8550-4b13-a0c5-054aa5bf07fa.png</url>
      <title>DEV Community: Unkey</title>
      <link>https://dev.to/unkey</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/unkey"/>
    <language>en</language>
    <item>
      <title>How to ratelimit tRPC routes with Unkey</title>
      <dc:creator>James Perkins</dc:creator>
      <pubDate>Fri, 17 May 2024 00:00:00 +0000</pubDate>
      <link>https://dev.to/unkey/how-to-ratelimit-trpc-routes-with-unkey-ppi</link>
      <guid>https://dev.to/unkey/how-to-ratelimit-trpc-routes-with-unkey-ppi</guid>
      <description>&lt;p&gt;Ratelimiting is not just a feature; it's a lifeline for production applications. Without it, you could face a skyrocketing bill. Your server could be pushed to its limits, leaving real users stranded and your application's reputation at stake.&lt;/p&gt;

&lt;p&gt;Unkey provides ratelimiting that is distributed globally and can be easily added to any server, ensuring your protection. We will discuss the features of our service, including synchronous and asynchronous protection, identifier overrides, and how our analytical data can help you identify spikes in usage and how it can be used in a tRPC application.&lt;/p&gt;

&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;p&gt;To get up and running with the app and follow along, you need:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A fundamental understanding of Next.js, primarily regarding routes and server-side data loading.&lt;/li&gt;
&lt;li&gt;Basic familiarity with tRPC.&lt;/li&gt;
&lt;li&gt;An application with user authentication implemented. This example uses Auth.js, but you can use any provider you like.&lt;/li&gt;
&lt;li&gt;Access to your &lt;code&gt;UNKEY_ROOT_KEY&lt;/code&gt;, which you can get by signing up for a free account&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In this post, we will use create-t3-app for the demo, so feel free to use that if you want an easy way to use tRPC + Auth.js in a Next.js application.&lt;/p&gt;

&lt;h2&gt;
  
  
  Installing the &lt;code&gt;@unkey/ratelimit&lt;/code&gt; package
&lt;/h2&gt;

&lt;p&gt;Before we start coding, we need to install the &lt;code&gt;@unkey/ratelimit&lt;/code&gt; package. This package gives you access to Unkey's API with type safety.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm install @unkey/ratelimit
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Updating our env
&lt;/h3&gt;

&lt;p&gt;We need to use the &lt;code&gt;UNKEY_ROOT_KEY&lt;/code&gt; to run our ratelimiting package, so we must first update the &lt;code&gt;env.js&lt;/code&gt; file in the &lt;code&gt;src&lt;/code&gt; directory. Add &lt;code&gt;UNKEY_ROOT_KEY: z.string()&lt;/code&gt; to the &lt;code&gt;server&lt;/code&gt; object and &lt;code&gt;UNKEY_ROOT_KEY: process.env.UNKEY_ROOT_KEY&lt;/code&gt; to the &lt;code&gt;runtimeEnv&lt;/code&gt; object.&lt;/p&gt;

&lt;p&gt;Now that it is updated add your Unkey root key to your .env as &lt;code&gt;UNKEY_ROOT_KEY&lt;/code&gt; which can be found in the Unkey dashboard under settings Root Keys.&lt;/p&gt;

&lt;h2&gt;
  
  
  Adding ratelimiting to a procedure
&lt;/h2&gt;

&lt;p&gt;Now that the package is installed and our &lt;code&gt;.env&lt;/code&gt; has been updated, we can configure our ratelimiter. Inside the &lt;code&gt;server/api/routers/post&lt;/code&gt; file, we have a &lt;code&gt;create&lt;/code&gt; procedure. This procedure allows users to create posts; currently, users can create as many as they like and as quickly as they like.&lt;/p&gt;

&lt;h3&gt;
  
  
  Configure our ratelimiter
&lt;/h3&gt;

&lt;p&gt;In this example, we will configure our ratelimiter in the procedure itself. Of course, you can abstract this into a utility file if you prefer. First, we must import &lt;code&gt;Ratelimit&lt;/code&gt; from the &lt;code&gt;@unkey/ratelimit&lt;/code&gt; package and &lt;code&gt;TRPCError&lt;/code&gt; and &lt;code&gt;env&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { z } from "zod";import { createTRPCRouter, protectedProcedure, publicProcedure,} from "~/server/api/trpc";import { posts } from "~/server/db/schema";import { env } from "~/env";import { TRPCError } from "@trpc/server";import { Ratelimit } from "@unkey/ratelimit";
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To configure the Ratelimiter, we need to pass four things along, the root key, the namespace, the limit, and the duration of our ratelimiting. Inside the mutation, add the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const unkey = new Ratelimit({ rootKey: env.UNKEY_ROOT_KEY, namespace: "posts.create", limit: 3, duration: "5s",});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The namespace can be anything, but we are using the tRPC route and procedure to make it easier to track in Unkey's analytics. We now have the ability to rate-limit this procedure, allowing only three requests per five seconds.&lt;/p&gt;

&lt;h3&gt;
  
  
  Using our ratelimiting
&lt;/h3&gt;

&lt;p&gt;To use the ratelimit, we need an identifier. This can be anything you like, such as a user ID or an IP address. We will be using our user's ID as they are required to be logged in to create a new post. Then, we can call &lt;code&gt;unkey.limit&lt;/code&gt; with the identifier, and unkey will return a boolean of true or false, which we can use to make a decision.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const { success } = await unkey.limit(ctx.session.user.id);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So now we have the boolean we can check if it's false and then throw a TRPCError telling the user they have been ratelimited and stop any more logic running.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const { success } = await unkey.limit(ctx.session.user.id);if (!success) { throw new TRPCError({ code: "TOO_MANY_REQUESTS" });}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;At this point, our code is ready to test. Give it a whirl, and try posting multiple times. You will see that the posts won't update anymore after you are rate-limited.&lt;/p&gt;

&lt;h2&gt;
  
  
  What about more expensive requests?
&lt;/h2&gt;

&lt;p&gt;Unkey allows you to tell us how expensive a request should be. For example, maybe you have an AI route that costs you a lot more than any other route, so you want to reduce the number of requests that can be used.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const { success } = await unkey.limit(ctx.session.user.id, { cost: 3,});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This request costs three instead of one, giving you extra flexibility around expensive routes.&lt;/p&gt;

&lt;h2&gt;
  
  
  Faster response
&lt;/h2&gt;

&lt;p&gt;Although Unkey response times are fast, there are some cases where you are willing to give up some accuracy in favor of quicker response times. You can use our &lt;code&gt;async&lt;/code&gt; option, which has 98% accuracy, but we don't need to confirm the limit with the origin before returning a decision. You can set this either on the &lt;code&gt;limit&lt;/code&gt; request or on the configuration itself.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const unkey = new Ratelimit({ rootKey: env.UNKEY_ROOT_KEY, namespace: "posts.create", limit: 3, duration: "5s", async: true,});// orconst { success } = await unkey.limit(ctx.session.user.id, { async: true,});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;While this is a small overview of using Unkey's ratelimiting with tRPC, we also offer other features that aren't covered here, including:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Overrides for specific identifiers&lt;/li&gt;
&lt;li&gt;Metadata&lt;/li&gt;
&lt;li&gt;Resources flagging&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can read more about those features in our documentation on &lt;a href="https://www.unkey.com/docs/ratelimiting/introduction" rel="noopener noreferrer"&gt;Ratelimiting&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>tutorial</category>
      <category>ratelimit</category>
      <category>otp</category>
    </item>
    <item>
      <title>Unkey raises 1.5 million pre-seed</title>
      <dc:creator>James Perkins</dc:creator>
      <pubDate>Wed, 15 Nov 2023 00:00:00 +0000</pubDate>
      <link>https://dev.to/unkey/unkey-raises-15-million-pre-seed-5f4n</link>
      <guid>https://dev.to/unkey/unkey-raises-15-million-pre-seed-5f4n</guid>
      <description>&lt;p&gt;The Unkey pre-seed round was led by &lt;a href="https://www.essencevc.fund/" rel="noopener noreferrer"&gt;Essence VC&lt;/a&gt; and joined by &lt;a href="https://www.linkedin.com/in/liujiang1/" rel="noopener noreferrer"&gt;Sunflower Capital&lt;/a&gt;, &lt;a href="https://new-normal.ventures/" rel="noopener noreferrer"&gt;The Normal Fund&lt;/a&gt;, and some fantastic friends.&lt;/p&gt;

&lt;h2&gt;
  
  
  Essence VC leads our round.
&lt;/h2&gt;

&lt;p&gt;When we met Tim Chen for the first time, Andreas and I were blown away by his experience and his immediate understanding of our vision. We only needed ten minutes before we were bouncing ideas and thinking about where to go with Unkey.&lt;/p&gt;

&lt;p&gt;Tim also introduced us to our other partners (Sunflower Capital and The New Normal Fund), who were just as excited to see how API authentication and authorization could be simplified.&lt;/p&gt;

&lt;h3&gt;
  
  
  Angels
&lt;/h3&gt;

&lt;p&gt;Our angels are a fantastic group of people in no particular order:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Andrew Miklas (Functional Capital / Ex PageDuty Co Founder)&lt;/li&gt;
&lt;li&gt;Ant Wilson &amp;amp; Rory Wilding (Supabase Co Founder / Head of Growth at Supabase)&lt;/li&gt;
&lt;li&gt;Paul Copplestone (Supabase Co Founder)&lt;/li&gt;
&lt;li&gt;Theo Browne (Ping / YouTube / Twitch / Twitter)&lt;/li&gt;
&lt;li&gt;Ian Livingstone (Startup Advisor / Investor)&lt;/li&gt;
&lt;li&gt;Preston-Werner Ventures (Led by Tom Preston-Werner Co-Founder of GitHub)&lt;/li&gt;
&lt;li&gt;George &amp;amp; Chris Perkins (James mum and dad)&lt;/li&gt;
&lt;li&gt;Zain Allarakhia (ex Pipe)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  How it all started
&lt;/h2&gt;

&lt;p&gt;Andreas and I started Unkey in the middle of June and launched on June 21st, the community loved Unkey and we got some awesome feedback. Once we understood that this side project, which started as a way to solve an annoying problem we both had experienced, was needed by more and more people, we set our sights on building an entire business for it.&lt;/p&gt;

&lt;p&gt;We worked nights and weekends for months to ensure Unkey made scaling user-facing APIs more accessible than ever. Shout out to all the friends and family who supported us getting through the 16+ hour days.&lt;/p&gt;

&lt;h2&gt;
  
  
  How's it going
&lt;/h2&gt;

&lt;p&gt;Since the launch in June, we have had success with the product:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;1.2k stars on &lt;a href="https://github.com/unkeyed/unkey" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;We have done over 13 million API key verifications.&lt;/li&gt;
&lt;li&gt;1.6k users have signed up&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What's next?
&lt;/h2&gt;

&lt;p&gt;Now that Unkey is funded, we can focus on building the best developer experience in the API space. You may be wondering what is next.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Hiring 1-2 more engineers.&lt;/li&gt;
&lt;li&gt;Create an easy-to-use permission system that allows you to control access through RBAC, ABAC, or REBAC.&lt;/li&gt;
&lt;li&gt;Create a new gateway system that allows any developer to understand and configure.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Talking about hiring, if you are interested in being part of the team. Check out the &lt;a href="https://dev.to/careers"&gt;job posting and apply&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Thank you for all the support, and we look forward to bringing API scalability to developers like never before.&lt;/p&gt;

</description>
      <category>preseed</category>
      <category>vcs</category>
    </item>
  </channel>
</rss>
