🛑 Stop paying for other people's traffic!

I'll be honest: until recently, I hadn't given much thought to HotLink Protection for my personal projects. But as I started optimizing the architecture of my blog (cloud-record.dev) for cost and performance, it suddenly made perfect sense.
What is Hotlinking? It's when another website imbeds your images or assets directly, using your URL. Their site looks good, but YOUR AWS bill goes up because you are paying for the data transfer. Not cool. 💸
For a media-heavy site (I serve optimized .avif images), this can be a silent budget killer.
Here is how I built a robust, serverless solution using Terraform and AWS CloudFront Functions:
Perimeter Defense: I created a CloudFront Function (running at the edge) that inspects every incoming request for my media subdomain.
Referer Validation: The function checks the
Refererheader. If it's not fromcloud-record.dev(or itswwwversion), the request is instantly blocked with a403 Forbiddenresponse—before it even reaches S3.3️⃣ Smart Exceptions: To make sure my content is still shareable, I added logic to allow empty referers (direct access) and, crucially, to allow bots from social media platforms (Twitter, Facebook, LinkedIn, etc.) so link thumbnails still work.
The result? A secure, highly-cached CDN that only serves my users, significantly reducing unnecessary Data Transfer Out (DTO) costs.
Building on AWS is not just about writing code; it's about smart infrastructure decisions that protect your budget.
Check out the diagram below to see how the flow works! 👇

But not all Domain providers gives you a WAF so this will fix that issue
take the code here for your AWS CloudFront distribution https://gist.github.com/ucapistranmtz/95ec83e60f8521832afab2d5eab9eeae
no way! you could see it here !!
function handler(event) {
var request = event.request;
var headers = request.headers;
var referer = headers.referer ? headers.referer.value : "";
var userAgent = headers["user-agent"]
? headers["user-agent"].value.toLowerCase()
: "";
if (!referer) {
return request;
}
var socialBots = [
"twitterbot",
"facebookexternalhit",
"linkedinbot",
"whatsapp",
"telegrambot",
"slackbot",
];
var isSocialBot = socialBots.some(function (bot) {
return userAgent.includes(bot);
});
if (isSocialBot) {
return request;
}
var domain = "your-domain.com";
var regex = new RegExp("^https?://(www\\.)?" + domain.replace(".", "\\."));
if (!regex.test(referer)) {
return {
statusCode: 403,
statusDescription: "Forbidden",
};
}
return request;
}
Support the Journey.
I create content and share knowledge from the serverless frontier. If you found this helpful, consider buying me a coffee!
Buy me a coffeeComments (0)
You must be logged in to comment.
Login to Comment