Architecting Antiquoted

This description of the Antiquoted technical architecture is not an attempt at bragging. I just thought it would be a good way of living out our aspiration for transparency as we build Antiquoted. And you never know, someone (somewhere) might find it useful.

By Jason Kelly

schedule September 16th, 2024

Dear reader,

I want to start this missive with a request for clemency.

I’ve been an interweb builder for quite a few years now, and I’ve helped to build some fairly cool things (in my tight-lipped estimation), but I am by no means perfect. I do many things badly, some terribly, but I try my best not to do things with hubris. As such, this description of the Antiquoted technical architecture is not an attempt at bragging. I just thought it would be a good way of living out our aspiration for transparency as we build Antiquoted. And you never know, someone (somewhere) might find it useful.

I’m also reeeeally opinionated. In the “real world,” this is a great way to start interesting conversations, learn, and be corrected when I’m wrong. I’ve (unfortunately) found, that on the internet it does not achieve the same results. As such, if you think I come across as a reet know-it-all twat in this post, please run that comment through an LLM with a “make this a nice and constructive comment” filter before you send it along. Thanks.

Anyways, enough wanky bollocks, here’s how it all fits together.

Antiquoted Frontend

The frontend is a statically compiled SvelteKit SPA (Single Page Application). It’s written in TypeScript, we’re using Bootstrap for styling (I know, I’ll migrate to tailwind at some point), along with Material (via SMUI) as the design system.

We use Tanstack Query as a request layer to talk to the backend API (more info below), which is a pretty hecking great way to handle caching and data-sharing between different components and pages.

Antiquoted Backend

Our backend is written in Python, using the Django framework. We use the django-ninja library to serve most of our data & functionality to the frontend and it is excellent! If you’re still using DRF, do yourself a favour and take a look.

Why Python? Partly because it enabled some much more useful framework choices (see below). Partly because it gave me an excuse to dive into some of the newer features (e.g. async) that weren’t around last time I was a 100%-full-time python dev. Mainly, though, it’s just a good language, so why not?

Why Django? The batteries are included. We get a super-powerful admin panel “for free.”I also get a really nice and powerful ORM for free, not to mention a bazillion useful functions that I don’t want (or trust myself) to roll myself, such as password resets. TL;DR: Django is rad.

Why django-ninja? It’s a much lighter, modern, flexible, asynchronous, pydantic-y flavor of “how to do an API on Django.” In retrospect, I’m super happy I chose it over rolling my own (as I have previously, rather than dive into DRF prescription-land).

Random useful-AF library shoutouts

  • easy-thumbnails & Pillow: Ain’t nobody got time for cropping user avatars manually.
  • django-storages & boto3: Outsourcing media is nice
  • algoliasearch-django: We curate your data, searching it is a solved problem that I don’t wanna have to host myself. So far my experience with algoliasearch is awesome, though their default django integration is lacking. I’ve already forked it a bit to get some of the functionality we needed for Antiquoted.
  • django-ratelimit: My first mentor taught me many lessons, but the best one: “everything must have a limit, even if it’s big”.

Antiquoted Infrastructure

BEZOS FOR GOD-EMPEROR

Jokes, mostly. Anyways, we use AWS for the majority of our infrasturcture hosting.

Why?…. It has nothing to do with their over-generous and well-complemented free tier. It’s definitely cause it’s the best. More jokes aside, the flexibility and stability that come with running an infrastructure on AWS are pretty underrated in my experience. It’s a stalwart for a reason.

That said: we could have built this on GCP just as easily, just maybe not as easily for me. So maybe personal preference/experience (as with all things) has an impact here.

I’m going to go into the whats and whys one-by-one here to hopefully make it clearer to those who have strong infrastructure opinions. Please understand this is just “how I plumbed it together”, and I totally acknowledge that this will likely change a bunch over time as we grow, and is strongly influenced by my experience rather than an aspiration for “the perfect infrastructure setup”.

Code-hosting-and-CI/CD-provider: Github

Why: My main alternative was Gitlab (which I’m a major fan of). I wanted an excuse to try out Github actions a bit more, and I liked their much more generous build allowance on the free tier 😉

Infrastructure-as-code framework: Terraform

Why: It’s the front-runner. I prefer it’s declarative approach to Pulimi’s “kinda procedural” one. And I would rather offer my (theoretical) first-born to cthulu than deal with the hell that is CloudFormation.

Database: Postgres, running on AWS RDS.

Why Postgres: It is the best relational database that I have worked with (in my rather-biased opinion). I’ll upgrade when I find something better.

Why RDS: I don’t want to be dealing with reliability and backups myself. RDS solved that years ago.

Container orchestration: AWS ECS, using an Autoscaling Group for nodes.

Why: Simplicity and reliability. I’m a one-monkey band. I’ve worked professionally with more portable and expansive solutions before (Kubernetes), but I also don’t want to spend my time managing these. My time is much better spent building useful features for our Antiquoters than it is dealing with K8s upgrades or sidecar perils.

Loadbalancing, Certificates + CDN, DNS: AWS ALB/ACM + Cloudflare

Why AWS: The loadbalancing goes hand-in-hand with our ECS usage, and ACM makes provisioning all of our certificates and serving them pretty trivial. I’d maybe have gone full AWS if Terraform/IaC wasn’t a thing, but hooking the CloudFlare & AWS providers up is easy as heck.

Why Cloudflare: Cheap/free and rather powerful DNS/routing tools. Ubiquotous CDN. If Cloudflare goes down, so does the rest of the internet. Antiquoted is the least of your worries.

Asset storage: Cloudflare R2

Why: It’s like AWS S3 but significantly cheaper. The only downside I’ve hit here is that write performance is significantly worse than S3 in my experience (200ms → 1500ms). Thankfully, after a recent region migration (bye-bye Singapore), things have become a lot more reasonable, so this is something I’m keeping an eye on. I’m not ruling out moving to an S3 + Cloudflare CDN solution in the not-too-distant future, though.

Why not use a platform-as-a-service like vercel?: Because I can. More specifically, because I know how to fit it together without relying on those services, and the outcome is that:

  • I have the flexibility to configure the infra how I need.
  • I can do things much cheaper than their pricing layer (and lack of features) constraints.
  • I’m less “baked in”. If I wanna port to GCP in the future, the “run a container somewhere” paradigm stays the same.

Got more questions? Leave a comment, or send me an email and I’ll get back to you.

Profile photo of Jason Kelly
By Jason Kelly

Antiquoted Founder, CTO & Prime Code Monkey. Responsible for all the (hopefully occasional) bugs you might come across.