Arjan effectively demystifies the transition from polling to event-driven architecture by emphasizing the necessity of decoupling. It is a concise blueprint for building professional-grade APIs that are both scalable and architecturally sound.
Deep Dive
Prerequisite Knowledge
- No data available.
Where to go next
- No data available.
Deep Dive
Your REST API Needs WebhooksAdded:
Take a look at this API endpoints. What this is is a simple URL shortener.
Basically, somebody clicks a link. We then increment a counter, so we track how many clicks there are, and then we redirect the user to the target URL connected with the link. Let's first post a request to this API to create one of these links for us.
So, here we go. We now have a link with an ID. There is a short code, and we have as a target URL my website. Let's see what happens when I actually go to this link. Oh, as you can see, the redirect works, and we end up with my website. Now, imagine that you're building an integration on top of this.
You want to know when a link is clicked.
Now, one option to do that is, of course, polling. And this works, but it's also very inefficient, slow, and puts a lot of load on your API. Much better solution is webhooks. Instead of asking whether something happened, which is what you do with polling, your API actively tells you, "Hey, this just happened." And that's a massive improvement. It means fewer requests, you get real-time updates, simpler integrations overall, and I feel not enough APIs are adding this type of functionality. So, in this video, we're going to build webhooks into this link shortener API to show you how it works.
I'll show you a simple version first, then I'll show you a much better design.
This video is sponsored by Incogni, more about that later. Now, let's extend this URL shortener. When a link is clicked, we want some external system to react to it. So, that means we're going to need a simple webhook system. This is actually really straightforward to add. Here, I have very simple setup that does this.
So, I have a webhook base model. So, there's an ID. Each webhook has an ID.
You could also store this in a database if you wanted to. Uh there's a URL that's associated with it. And for now, that's it. Then, I have the input for creating webhook, which obviously expects this URL. Then I have a route that we can use where we create these webhooks. And this is where I store for the time being the actual webhooks that are being created. And like I said, you could also store this in a database, obviously. In fact, if you're building a production system, you don't want to store this locally on your server. It should be in a database. Now, what do we have then? Just a couple of simple functions. One function to deliver a webhook. This function has two arguments, the webhook which is of course what we need, and the data that needs to be sent to the webhook. And it does a simple HTTPX post request to that URL with the data in JSON format. And there's a little helper function that, given some data, we simply send this to all the webhooks. Finally, there's a couple of endpoints that we're going to need. Obviously, you can extend this with updating webhooks, deleting webhooks, and whatnot. But for now, we just have one for creating webhook, and we have one for listing the webhooks that are currently in the system. And that's it. In the main function, I create a FastAPI app, and I include the routers that I need, namely the links that we have to create these short links, and we have the webhooks router that I just showed you. Now, the only thing we need to do is post to these webhooks whenever something happens in the system. For example, here we have the redirect to target endpoint that we know that the link clicks are being increased, and that means that here we should now actually call these webhooks. What we're going to need for that is from the webhooks module, we will import the send webhooks function.
And then if I go to my redirect to target, well, of course we have to think about what we're going to send. So, let's define a payload.
Let's provide a type. Let's say link.clicked, and we can add more types later on.
Let's also provide a link ID.
>> So, this is going to be the ID of this link object.
We can supply the shortcode, which is what gives us the short URL.
We can provide the target URL.
And let's actually also turn that into a string just to be sure.
We can also supply the number of clicks, like so.
And we can even send along at what time the click occurred.
And for that, we're going to need date time.
And UTC.
And let's turn that into an ISO format, like so. So, this is our payload.
And then, we can simply call send webhooks payload.
Now, if I restarted the API, I need to create the link again. There we go. And this is the shortcode that we're going to need. And now, as the next step, let's create a webhook.
And as you can see, there is a localhost 8001. This is actually a little test server that I'm running here that listens to these webhooks. So, now once we have this set up, created the short link, and I created the webhook, I can take this shortcode, and we can see what happens when I navigate to this URL. So, here's my shortcode. Let's go here. As you can see, we end up again at the rmcode.com website. But if I now go to my test server, we see that, "Hey, we actually received the webhook." Which is very nice. And we got all this data that we passed as payload. So, this is exactly what we want. And now, we can build out our integration with this webhook system, which is really cool.
And now just to show that it actually tracks the number of clicks, let's go visit this link again. And now we see that we have another webhook that we received, and now clicks is two. So, this works really well. A webhook is literally an HTTP request leaving your system with data in it. And [clears throat] once that data's out there, you don't control where it ends up anymore. And that's not just a design concern, it's also a privacy issue.
That's exactly the problem that today's sponsor, Incogni, solves. Your personal data is already being distributed all over the internet through data brokers.
These companies collect and resell data sets with things like your name, address, phone number, and more. And that creates real risks. Targeted scams, identity theft, or just having way too much of your personal data exposed.
Incogni automates the process of removing your data, finding where your data exists, and sending legally valid removal requests to those companies.
Now, instead of doing that manually hundreds of times and repeating it whenever your data shows up again, Incogni handles that continuously in the background. Now, as a semi-public person, being a YouTuber, I'm really careful with where my personal data goes. And just after creating an Incogni account, they already sent a removal request to over 50 data brokers. That's just insane.
And with their custom removals feature, you can send them a specific URL and they'll take care of removing your data from that site. So, instead of your data being continuously redistributed, you're actively reducing the footprint across these systems.
I highly recommend you check them out.
Click the link in the video description and use code iron codes to get 60% off an annual plan.
Now, back to our API. What I I now is that I sent a payload to the webhooks whenever there's a redirect. But, of course, that's not the only place where you could do. You could do this in different areas of your API. For example, let me just copy this over.
There's also a create short link. So, maybe you also want to inform the webhooks whenever you actually create the link. So, let me just copy-paste the payload here. So, this is a type link dot created. And we can supply all of these things. The clicks we're not going to supply because of course there are no clicks yet and clicked at we also don't need. So, now I've created another point where these webhooks can be informed.
But, you already see a problem that's occurring here. These endpoints, if you look at what they actually need to do is of course they need to they contain the logic. Now, you could potentially go to a ports and adapters setup where you put this logic outside of the router. But, the problem is still that you have logic related to links. So, to tracking, clicking, uh doing the redirects, etc. etc. But, also the logic now needs to know about payloads and webhooks and things like that. And as your system grows, you know, now we just have this here and in the create short link place that's not that much. But, this is now place where the code needs to know about webhooks. And as your system grows, you're going to repeat this everywhere.
And that introduces a lot of coupling.
So, how would you properly design this?
Well, instead of saying, "Hey, send to the webhooks." Actually, what we can also say is something happened. A link was clicked. A link was created. That's a fact, an event that occurs in a system. I think you already got an idea of where we're going with this. So, instead of sending it directly to webhooks, you could actually do it through an event bus, an event management system. And that way you decouple these things completely. So, what do you need for that? Well, you need some sort of minimal event system.
Uh this is what that could look like, right? So, we have an event type, link created or link clicked in this case, or you can add, of course, many more uh enum values here if you want to. You can create a whole hierarchy of events.
That's like the world is your oyster.
And by the way, where does that saying come from, the world is your oyster? I don't want to be in an oyster. Anyway, so we have the event. Uh then we have a listener function. Well, that's very simple. A listener function gets an event and returns none as a result. So, then, finally, we have a class event bus that has these listeners that map a certain event type, so that's links created or links clicked, to a bunch of these listeners. We have a subscribe method that gets an event type and a listener and then adds that to the dictionary. I'm using set default here so that if there is no uh list yet, it will create this by default. And then we simply add the listener. And publish, where basically we have some event that happens. There is some data that's associated with the event. We then create that event object. You can also decide here to actually store that event in the database, create endpoints so that you can actually read back the events, which is also really cool thing that you can do with an event-based system. So, you can track what's happening in your API.
I'm not going to build that now, but that is really cool. And then, the only thing I'm doing here in my event bus is that I check all the listeners for this particular event type uh with the default value of the empty list, and then I'm simply calling those listeners with the event. And now, this is really nice because this gives us a mechanism of decoupling webhook calling from events that happen in the API. So, now let's patch this event system into our app. So, first, in the main function, from the events module, we're going to import the event bus.
And then let's create the event bus object in the main function. Now of course we need a way to pass the event bus to our links because links now need to send an event whenever we're clicking or creating a link. One thing we can do is define a function here. Let's call that configure and that's going to get I typed bug there. Did you notice that?
Event bus like so and of course from events we're going to import event bus. And then for now let's say there is this global dirty variable event bus.
Event bug I I don't know what's going on with me. Okay, I'm now assigning this value to our global event bus variable.
There we go. So now what I can do in my main function is that from links I can now pass the event bus, not bug.
There we go. And what I can do now is instead of this bit here, I can now use the event system. So what I'll do here is event bus. publish and then we're going to need the event type which we will also import.
So this is link created.
And then we have our payload.
And this I'll remove.
There we go. And same thing for the redirect.
And clicked and then we're simply going to pass the payload right here.
Like so.
There we go. The nice thing here is that the links module now no longer has any knowledge about web hooks because that's handled by the events, right? You can now also update the web hooks system so now it works with our event bus. So, the first thing we need to do is together with the ID and the URL that we already had in the web hook is that we add this list of events that the web hook is for so we can send different web hooks for different types of events.
Then, we have a web hook create model so this is what is passed to the API. So, this is not only gets the URL anymore but it also gets a list of events that it should be connected to.
I'm storing these web hooks here just like before and then just like with the links, I have a configure function here that makes sure that we have access to the event bus. And of course, in my main function I also needs to call that configure function without the slash.
Like so. Delivering the web hook also changes now slightly because it gets an event now and then we do a model dump from that event object.
So, the JSON data that we get is the contents of this event. Then we have a function that given a web hook make sure that it listens to events. So, this calls the subscribe method for that particular event. So, there we have a lambda function that gets an event and delivers it to the web hook. And then finally, in the create web hook endpoint, we attach the web hook to the listener. And that's the only thing that we need to do here. So, now the event system is in between. Web hooks don't know anything about links. Links don't know anything about web hooks. That's what the event system is for. Now, let's again create a link. There we go because we restarted the API and I'm not storing any of this information so that's what we have. So, now let's create a webhook, and I'm doing that for a particular type of event, namely link.clicked.
So, there we go. The webhook is there.
Now, let's see what happens if I navigate to that particular link. Here we have the link URL.
I open the page, and of course it redirects to the Iron Code's website. If I go back to our test server, we now see that we received again a webhook just like before, and we have the data, which is the event that we created.
Let's do this one more time. And again, we've received the webhook again with the second click. In terms of design, this is much better. It looks like a small thing to do, but it does change a lot because now you can add analytics, logging, fraud detection, background jobs without touching any of the endpoints in the domain. And that's a really useful extension of the API. Now, of course, this is still a simple example. If you have a real system, you will need many more things. You might want to add retries, async processing, tracking delivery, authentication, encrypting data that is sent to webhooks, rate limiting. Also, the system is currently quite limited in that whenever I call this endpoint redirect the target, I'm actively publishing that to an event bus, which is then directly sending HTTP request to the webhooks. You should not couple that directly, but probably use a queue.
But, the event-based system that we have makes those improvements possible without rewriting everything. Cuz even adding a queue, we don't need to do any work here. We can do that on the event [clears throat] bus side. And that's the power of thinking a bit ahead and thinking about the design that you're going to need for systems like this.
Now, if you found this useful, like this video, subscribe to the channel. Not only helps me grow here on YouTube, it also tells me to make more videos or less, like this. Now, webhooks, I think they're a huge improvements over polling and REST APIs, and more APIs should add these, but it matters how you design them. Uh just a direct simple webhook calls, they're fine if you just want to get started with it. But, in my opinion, events give you a way cleaner and more scalable design. Now, the full code example of this uh webhook setup is in the Git repository. The link is in the video description.
But, I'm also curious to hear what you think. Have you built APIs like this before? Have you thought about webhooks, integrations, event handling? How did you build it? Let me know in the comments. Thanks again, Incogni, for sponsoring this video. Make sure you check them out through the link in the description. And YouTube thinks you might like this video next. Thanks for watching, and see you next time.
Related Videos
Agentforce NOW AMA: Build with React and Salesforce Multi-Framework
SalesforceDevs
490 views•2026-05-28
How agent o11y differs from traditional o11y — Phil Hetzel, Braintrust
aiDotEngineer
450 views•2026-05-28
WEB TECHNOLOGIES UNIT-2 | Degree 4th sem BCOM Computers web technologies unit-2 full explanation💯✅
LearnwithSahera
1K views•2026-05-29
More tests are always better? How to use AI to identify tests that bring little value
Alliance4Qualification
335 views•2026-05-29
Search Algorithms Explained in 60 Seconds! 🤖💨
samarthtuliofficial
218 views•2026-06-01
People of Game of Thrones using JavaScript DOM
AltCampus
296 views•2026-05-30
Introduction to Problem Solving Part - 1 | Lecture 1 | Intermediate DSA
ascensionix
107 views•2026-05-29
So What's Odin Lang Even Good For
TechOverTea
131 views•2026-06-01











