Skip to content


Switch branches/tags

Name already in use

A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?

Latest commit


Git stats


Failed to load latest commit information.
Latest commit message
Commit time


DNS-driven url shortener (it's a toy I built to get more comfortable with AWS CloudFormation templates)

Built with AWS Route53 + AWS S3.


Just a toy project to explore these tools. I wanted to explore CloudFormation templates, I noticed .link domains are only $5/year, and I wanted to know if I could build a URL shortener without application layer code.

And.... no, I couldn't. See "How does it work" below

As summarized in this Stack Overflow answer

No, what you ask is not possible. DNS is name resolution system and knows nothing about HTTP.

This is probably not a good idea

I'm not suggesting this is a good idea for operating a url shortener at scale. It's too read-optimized in my opinion ... to write a new shortened url it could take minutes since it's a cloudformation update-stack call which needs to make a new Route53 record (and a new S3 bucket).

I don't see any significant improvement over looking up the slug in a database and generating an http redirect response on the fly. But, I think what I've built is interesting and marginally useful, so I'm satisfied.


Add an entry to ./redirects and then re-publish.



or if it's the first time deploying or you want to blow everything away first:

src/ --clean


  • Add GitHub action to update CFN stack on push
  • I think CFN supports nested stacks... but one way or another, it would be nice to replace the bash house of cards build scripts with something more sensible and idiomatic.

How does it work

First, let's compare with what we get when we curl a URL

$ curl -v
*   Trying
* Connected to ( port 80 (#0)
> GET /36CLbfg HTTP/1.1
> Host:
> User-Agent: curl/7.54.0
> Accept: */*
< HTTP/1.1 301 Moved Permanently
< Server: nginx
< Date: Fri, 11 Dec 2020 00:05:42 GMT
< Content-Type: text/html; charset=utf-8
< Content-Length: 124
< Cache-Control: private, max-age=90
< Location:
< Set-Cookie: _bit=kbb05G-0fa3c505dfb5b90b9a-00R;; Expires=Wed, 09 Jun 2021 00:05:42 GMT
< Via: 1.1 google
<body><a href="">moved here</a></body>
* Connection #0 to host left intact

The interesting bits: returns

  • an HTTP 301 response
  • a Location header with the new destination
  • a Server header that tells us uses nginx
  • some HTML with a link to the new page -- which RFC 2616 (which describes HTTP 301) says "SHOULD" be present in the response:
    • "Unless the request method was HEAD, the entity of the response SHOULD contain a short hypertext note with a hyperlink to the new URI(s)."

And here's

$ curl -v
* Rebuilt URL to:
*   Trying
* Connected to ( port 80 (#0)
> GET / HTTP/1.1
> Host:
> User-Agent: curl/7.54.0
> Accept: */*
< HTTP/1.1 301 Moved Permanently
< x-amz-id-2: HuCfFNGEF5gaeJNifXbch2n6F6HwsPJC+53MLthfLjJcY8C4PnaLLbDpsoxz4i7VaFTAEvxT19k=
< x-amz-request-id: EA6559746AC9F219
< Date: Fri, 11 Dec 2020 00:09:39 GMT
< Location:
< Content-Length: 0
< Server: AmazonS3
* Connection #0 to host left intact

The important stuff is the same thing: HTTP 301 with a Location header. Also

  • the Server header indicates it's AmazonS3
  • there's no HTML response

So what's different?

  1. uses DNS entries instead of database entries for mapping shortened urls to full urls. Technically this is faster for reads, but it's way more complicated for writes... and does anyone need a faster URL shortener? I don't think so.
  2. uses Amazon S3 instead of NGINX + custom code for returning the HTTP status codes... which might seem like less operational load, except that each link needs its own bucket which is a separate deployment, so it would probably be way more painful to operate.
  3. Apparently Amazon S3 ignores the "SHOULD" note from the HTTP 301 RFC by not sending any HTML with the link to the new page. But... unless your browser doesn't know what to do with HTTP 301 (?!), I can't see this being a problem.
    • <pedantry>In any case SHOULD is optional if you have a good reason so it's not technically deviating from the spec as long as for the folks in Amazon S3 it's true that "the full implications [are] understood and carefully weighed before choosing [this] different course" 😉


No description, website, or topics provided.






No releases published


No packages published