Reviewing My Past Infrastructure, Technology and Product Decisions
Your mileage may vary: here are some real life experiences
We are usually thinking about the future but it can be a good exercise to review decisions made in the past and check how well they held up. Inspired by this post, I want to use this post to review some product and technology choices which I pushed forward.
No matter how much we try to look at things objectively: choices are always biased to a certain degree. And it is not about bashing tools or vendors but about critically reviewing things that worked out for us and those that did not. That being said, let’s dive in!
The legend is as follows:
- ✅ Recommend, I would likely do this again
- ⚠️ Works to a degree but with drawbacks and would consider alternatives
- 🛑 Would likely not attempt to do this again
✅ Linear
Can Jira make sense in your organization? Sure. Is it overloaded and are there better alternatives? Definitely! Linear is not only great at what it does (helping us to plan and manage software projects effectively) but there is a lot to learn in how they do things (keyboard support, performance, UX design). Linear is worth the price point and we are very happy using it.
(✅) Netlify
Netlify is a great choice for hosting web projects. The Netlifolks created a simple yet solid platform to host any kind of web app. The developer experience is neat, especially when it comes to serverless.
The only downside for us is that this comes at a cost: Netlify is not as configurable or extensible if you need more power. And if you’re not 100% serverless then you will still need to use another cloud platform like AWS.
✅ Cloudflare
Cloudflare does almost anything Netlify did for us yet it offers much more. I find the developer experience slightly worse than Netlify and I feel that configuration and the CLI could harmonize better. But at a similar price Cloudflare offers a lot of helpful goodies, especially around security such as a WAF (web application firewall) and AI (e.g. AI Workers). Overall, Cloudflare has been pretty reliable for us since setting things up.
✅ (Render)
Do you like AWS but you want to reduce maintenance and setup costs? Then Render might be a good choice for you. Similar to Netlify, it appeals strongly to startups and fast growing companies. With Render it’s simple to deploy and run a service: either by using the straightforward UI or by using infrastructure-as-code (which is what we do).
The main downside is that other tools may not provide a simple solution to connect with Render (AWS, GCP and Azure usually fare well in this regard). Of course Render does not offer all possible customization options that AWS would offer but the team is constantly shipping useful features that work. FWIW: Render is built on top of AWS.
⚠️ Serverless Functions
Personally, I am torn when it comes to serverless functions. As a user I like to have serverless as an option to only pay for what I consume. As a developer I like it when building a frontend that needs a backend part: serverless is handy for prototyping. But when it comes to developing and running those serverless functions in production on our own (e.g. with Cloudflare) I still prefer a “proper” backend service. While it may not always make sense for my own code I do like the serverless model in some products we use ourselves.
✅ Angular
Angular has evolved steadily over the last years. I feel it started to pick up significant pace since Angular 14 with the introduction of standalone components. Signals are another thing that make building reactive UIs easier as well. Of course, React’s ecosystem is still bigger but I rarely find this to be an issue in practice except rare cases. Angular is a framework and I like this fact.
✅ Nest.js
Overall, we are quite happy with Nest.js. If you like Angular you will Nest as well. Express.js is fine but I like the project structure and the testability that Nest brings out of the box. Similar to Angular, Nest is a framework and I like this fact.
✅ Prettier
It’s 2024, I do not want to deal with manually formatting code or even comment on PRs that things should be formatted in a certain way. Prettier takes care of this.
✅ Using a dedicated Log Management tool
We are using BetterStack Telemetry and it works pretty well for us. Log based alerts are a simple yet powerful way to deliver notifications over multiple channels to notify the team in case of issues. We have also created a bunch of presets for common scenarios such as to find endpoints with slow response times.
Their friendly and helpful support has been pretty stellar and deserves a special mention.
✅ GitOps
Git all the way. CI/CD or bust. Which brings me to…
✅ GitHub Actions & Workflows
Since GitHub introduced GitHub Actions, GitHub finally won me over GitLab. Similar to npm packages, there is probably an action for whatever you want to do. And if there is not then it is often not that hard to create a custom workflow.
As someone who has created a bunch of workflows: while act helps with local development and debugging workflows I wish GitHub would release more official tooling to simplify development.
⚠️ Jest
When Jest works it is great. There is a big ecosystem, the CLI is awesome and it works decently well with common frameworks. For me it was a big step up compared to Jasmine which I was used to before.
But if it does not then it can be quite annoying to deal with. I am not referring to missing web features unsupported by jsdom, I am talking about issues around TypeScript support and module imports causing test failures. While we are not actively looking to replace Jest at the moment I am keeping my eyes open for other test runners (e.g. vitest).
✅ Testing Library
Testing Library is a lightweight solution to write UI component tests that rely on minimal implementation details and focus on user behavior instead. In our case, it is Angular Testing Library to be precise. In many cases writing tests with Testing Library has helped us uncovering usability issues like poor accessibility (e.g. a button with no text). There had been a few breaking changes when upgrading to the next major version but our overall experience has been pretty good.
✅ Testcontainers
You should write integration tests. And we find Testcontainers to be a helpful to do so. Spinning up containers (e.g. a Postgres database) to test endpoints end-to-end becomes easy with Testcontainers.
(✅) Nx
Nx is a helpful tool to help us divide and manage our different product parts in a consistent way. The caching of task outputs is pretty nice as it can speed up local and especially CI workflow executions, saving CI minutes. That being said, updating Nx to the latest version has not always been trivial for us in the past and Nx can feel intimidating at first. Overall, it is still a strong net positive for us.
✅ Just use Postgres
Just use Postgres until you have a very good reason to use a database for special databases, e.g. a vector database. Postgres is open source and there has a large ecosystem around it.
⚠️ MongoDB
I like MongoDB in the early phases when all I need would be a database that takes anything and gives it back to me. MongoDB Atlas is a pretty compelling offering that I liked using in the past.
Nowadays, I rarely find a case where I would prefer MongoDB or other NoSQL databases over Postgres: SQL does have some benefits after all and jsonb
can be used if we want to store arbitrary data as JSON. If you are not staying up-to-date with MongoDB you will have a bad time: a good friend of mine can tell you all about it.
✅ Prisma
Prisma is a fine ORM that plays well with TypeScript. We are generally quite happy with it. A considerable downside (and I guess this applies to other ORMs): by making it so easy to create sophisticated queries it naturally becomes easy to create pretty expensive SQL queries with Prisma.
✅ Sentry
Setting up Sentry is dead simple when getting started. The most important thing for us is the error monitoring and this is what we primarily use Sentry for. I am looking forward to seeing further improvements in performance monitoring.
⚠️ Cloudinary
Cloudinary is a solid product but it is not the best solution in all cases. If you are looking for a service handling all kinds of files (images, PDF, Excel, ZIP, …) you are better off looking at Amazon S3 or similar alternatives such as DigitalOcean Spaces or Cloudflare R2. If all you store are images and videos then Cloudinary is still a good tool with a nice admin dashboard.
✅ DigitalOcean Spaces
DigitalOcean Spaces is a simple to use solution for object storage. Their pricing is pretty fair and predictable. A huge advantage: its API is mostly compatible to Amazon S3 which means it is often compatible to tools that are compatible with S3.
🛑 Clarity
It’s free and easy to setup so I shouldn’t complain about Clarity. The video quality was shaky and inconsistent. Hence we dropped it. Maybe it works better on static websites.
⚠️ Snyk
Snyk is a solid product for analyzing code and dependencies. It hooks in nicely as a CI check in PRs and it can be invoked with their CLI as well. While I do not always agree with the way they rate vulnerabilities I do not find this to be a big issue in practice.
The thing that currently bothers me the most is a feature that is actually pretty neat: the creation of fix PRs that upgrade dependencies to a newer patched version. Unfortunately, despite my best efforts Snyk still occasionally creates PRs for dependencies that I explicitly excluded to be ignored (e.g. it should not create PRs for TypeScript as we’d typically upgrade TypeScript when upgrading Angular as well).
✅ Sendgrid
Sendgrid is a solid choice for sending emails. Note that even if you are not sending too many emails yet I would recommend to get a static IP address: without a static IP address your emails will more likely be blocked by corporate email filters.
✅ Transifex
Sooner or later, your will probably need to support more than one language. I toyed around with other translation management tools but I eventually settled with Transifex. Collaboration works well and the GitHub integration is pretty neat: if it could only stop formatting files which creates larger PRs than necessary then it would be perfect.
✅ SnapShooter
When we think about backups most people probably think about backing up their relational database. But what about files uploaded by users — those are usually managed in a tool like S3. It took me a bit to set up a backup job in SnapShooter (and one major f*ck up when I accidentally deleted all files— luckily, I had previously downloaded all files locally hence I could restore before customers noticed anything; this is a tale for another time) but the daily backup job is now working reliably and I feel more at ease.
✅ Metro Retro
If you are doing retrospectives (and you should do it from time to time) then I can recommend Metro Retro. Not only do I like the name, it also provides the essentials for conducting a retro including nice templates and the ability to throw confetti. Figjam or Miro are also decent alternatives.
These tools help but in the end, it is a team effort to conduct retros that help the team.
✅ Font Awesome Pro
The free version of Font Awesome is already pretty nice and the pro version builds up on the strong foundation, providing an icon for almost every case you will ever need.
One thing that slightly bothers me as a user is the private registry bandwidth: we are usually exceeding it since we have multiple GitHub workflows that call npm ci
and we push/deploy a lot. One way to solve would be to store the Font Awesome files in the repository instead of installing them through npm: hence I will not hold it against them.
✅ Linters
Stylelint and ESLint are two helpful tools to get actionable feedback in the IDE and on CI. I am a big believer of automating the things that can be automated: everything which can be enforced automatically and which removes guess work or need for manual documentation should probably be automated.
Some Stylelint rules which we found to be helpful are around enforcing consistency (e.g. keep variable names at the top of stylesheets) and common issues (e.g. prevent using certain selectors). When it comes to ESLint I find framework specific rules (e.g. angular-eslint, eslint-plugin-nestjs-typed) to be particularly useful, especially for engineers who may not be familiar with certain frameworks yet.
✅ GitGuardian
Secrets should be, well, secret. And they should also not be hardcoded. GitGuardian provides capabilities to fix hardcoded secrets in Git repositories. It hooks in nicely as a CI check in PRs and I get alerted in case it finds secrets in our source code.
⚠️ Pendo
Pendo is a good product analytics tool and it is not too difficult to get started with it. However, it is fairly expensive and I intend to review other alternatives that may cover areas as well such as feature flagging. I have heard good things about Posthog.
(✅) Leveling up your compliance and security efforts early
Does a startup in year 1/2/3 need to be compliant to frameworks like ISO 27001? Not necessarily but you probably know how things tend to go: the earlier you set up the right foundations, the less effort you need to make in the future when your organization has grown slower and less nimble.
We are using Drata which automates compliance and best practices around security in our company. It also helps us maintain our ISMS (information security management system). There are some tools that are similarly capable like Vanta and Secureframe but I am happy with Drata. The integrated guidance helped me quite a lot not only in setting up processes and policies but understanding why things are the way they should be.
🛑 Not introducing a MDM earlier
MDM (mobile device management) helps us manage and secure our devices. One useful feature is the ability to install software (e.g. VS Code) directly through the MDM, reducing the onboarding efforts for new colleagues. If you wanna pursue security certifications such as ISO 27001 or SOC 2, a MDM can help with getting your organization ready.
Depending on the OS there are a couple of good tools that cost fairly similarly (e.g. Jamf, Swif, Jumpcloud, Kandji). We are using Swif which works well for us.
Conclusion
Thanks for reading this post! It was interesting to look back and see how some things turned out better than expected and how there are still some things on my todo list. Let me know in the comments about your experiences.