I just realized the other day that my blog is in its fifth year now. Since the application is built from scratch, I figured it would be fun to do a write-up of the architecture behind my blog.
My blog has always been a NodeJS/Express application, but lately I have made some changes to how it’s built and deployed. The first thing I changed was the underlying build system. Switching the build to Bazel made for a much more optimal build pipeline. Instead of a cobbled together Typescript build with custom Azure deployment scripts, I now do everything in Bazel. This allows me to set up a completely consolidated build pipeline.
Handling compilation of source code written in different environments is one of the strengths of Bazel, but compilation is usually not the leaf of the build process. The next step is typically to package up the build artifacts and deploy the application somewhere. In my initial solution I did a Git deploy to Azure, aided by a custom shell script. This approach worked reasonably well for years, but the script was kind of a mess. Every time I needed to make a change, I was reminded how brittle the approach really was. It ended up becoming a pain, so I decided to replace the custom build script with a Docker based Bazel solution. Now, as part of every release, I use Bazel to create a new Docker image that I push to a private Docker registry. I have a web container app running in Azure that I re-deploy based on the most recent Docker image. Before, my deployments used to be very slow since the build always started from scratch, but with Bazel my builds usually only take about 30 seconds since the entire build pipeline is incremental.
My articles and comments are stored in a MongoDB instance, but I rarely hit the database directly since all articles and comments are cached in the Node layer. This means I can get by with a very low end MongoDB instance, which helps keep hosting costs down.
Under the hood I use NodeJS with Mustache templates to generate articles dynamically, but there is not reason to regenerate the articles for every request. Instead I run a build time batch process to generate static html pages for all articles. This means my NodeJS server only needs to serve static html documents at runtime. On top of that I also cache the static html documents in the CDN. This helps reduce the resources needed by my server since there is no heavy code execution. More about this process in my other article about static html generation.