martyw.dev

My 2024 Tech Stack

What I'm reaching for this year — languages, frameworks, infra — and why.

Close-up of an orange-glowing microchip seated on a dark circuit board.

A snapshot of what I’m building with in 2024, based on what I’m already using and what’s lined up.

Two years on: My 2026 Tech Stack — what changed, what didn’t, and which calls aged badly.

Languages

TypeScript is the bread-and-butter. It’s the language I enjoy most, covers the most ground, and goes from backend to frontend without me having to think much about the join. Anything new defaults to TypeScript unless there’s a reason not to.

PHP I’d call a secondary skill at this point — I touch it rarely, but enough that keeping a baseline of competence is worth it for client work and the off-the-shelf solutions I lean on. PHP 8 has done enough interesting things to keep my interest from going completely cold, but Node remains easier to develop and maintain.

SQL is the one I’d push anyone with the time to learn. ORMs handle most of the day-to-day, but the ability to write, read, and optimise raw SQL is the difference between a backend that scales and one that doesn’t. Indexes, query plans, what a join actually costs — none of that goes away when you put an ORM on top.

TSX gets its own mention because the JSX/TypeScript blend is its own muscle to build. React is the context.

Bash for small scripts, mostly inside CI/CD pipelines. Nothing exotic.

Content management

Most of my work is bespoke, but a decent CMS still earns its keep on traditional websites and basic applications — anything that needs authentication, media uploads, and editable copy out of the box.

Craft CMS

I’ve been using Craft CMS for close to ten years. Over that time I’ve tried a fair share of alternatives — Strapi on the open-source side, Contentful on the SaaS side — and Craft remains the best balance of maturity and extensibility I’ve found. Since headless mode and the GraphQL API landed, it pairs cleanly with Next.js.

The team is small, focused, and actually present in their own Stack Exchange instance, GitHub threads, and Discord. The community produces high-quality plugins. The documentation is genuinely good. Clients learn the control panel quickly.

The downsides are honest ones. It’s PHP, so if you’re a TypeScript shop the language switch is a real cost — Strapi is the obvious alternative for that case. It’s built on Yii, which I find one of the weaker PHP frameworks; Craft’s docs occasionally hand you off to Yii’s for the harder questions, which gets old. The pricing model is also slightly odd — the free Solo edition gets updates forever, but the paid tiers cut you off from updates if you stop paying annually. And extending the control panel pairs Twig with some dated JavaScript that feels like stepping back a few years; a React control panel would be a welcome change.

Runtimes

Node.js

The primary runtime, and will stay that way. It’s the most stable, mature option for backend JavaScript, and that matters more than the new-shiny factor. The honest downside is the baseline resource demand — Node services aren’t cheap to scale horizontally compared to lighter runtimes.

Deno

I’m watching Deno. The native TypeScript support and the developer experience around it are appealing, and I’ll try it on a small project as it gets closer to the maturity bar I’d want for production.

Cloudflare Workers

Workers earn their keep at the edge. They sit early in the request path, so they’re the right place for token validation, request rewriting, and similar low-latency work. They also get programmatic access to the Cloudflare cache and to KV, Durable Objects, and R2. We use them heavily at work.

Frameworks

Nest.js

Five years on Nest.js and I haven’t found anything comparable in the Node space. It’s well-documented, the dependency injection model is clean, the modular architecture lets you design an application sensibly and ship community modules without friction. The CLI for scaffolding and hot-reload dev mode is good. There’s a lot of community work — first-party modules for configuration, task scheduling, Apollo, TypeORM, testing utilities, all of it stable.

Two real gripes. You can land in dependency hell trying to upgrade Nest alongside third-party modules — I’ve had upgrade chains where bumping Apollo forced a Nest core bump which broke other modules I needed. And it’s opinionated. If you don’t like the opinion, you won’t like the framework.

Next.js

Next.js (named annoyingly close to Nest.js) is the default for React applications that need both client and server functionality, plus a long list of other things you’d otherwise wire up yourself. It’s where I start most client work — broad coverage, strong docs, and an easy supply of other developers if I need to hand a project off, get sick, or just disappear on a deadline.

Vercel as the deployment target adds real DX on top — a few clicks gets you from a GitHub repo to a live preview a client can click through. ISR and SSG are good ways to keep a content-heavy site fast and your backend bills small.

The cost of that flexibility is a learning curve, particularly around the data cache. People who haven’t paid attention to how their fetch() calls behave get caught out by it. The line between server and client code can be subtle until you’ve made enough mistakes to internalise it. Version jumps can also be a project on their own — Vercel iterates fast.

React

The default for the same reasons it’s always the default — community, adoption, resources, DX. I started on Vue, and I have nothing against it, but React combined with TypeScript is just a sharper tool.

Tailwind

Writing CSS is one of my least favourite parts of building anything. Years on SASS didn’t change that. A few years on Tailwind has — I’ve shipped dozens of projects on it with effectively zero hand-written CSS. The community is large and produces enough drop-in components (Tailwind Components and similar) that you rarely start from scratch. IDE plugins give you intellisense against your theme. Onboarding other developers is cheap because the learning curve is small.

I’m aware of the criticisms. As a developer who lives mostly on the backend and just needs clean interfaces for internal tools and standard sites, they don’t bite me. The real downsides are honest: you have to learn the framework, which means absorbing a lot of class prefixes and how they combine; and once a project is built on Tailwind, getting off it is a significant rewrite.

Apollo GraphQL

Four years using Apollo with Nest. It’s the most mature GraphQL implementation in JavaScript and integrates with Nest cleanly. We use Apollo Federation to let teams own their own slices of the supergraph, which has been one of the bigger wins.

The thing to watch is Apollo’s commercial direction. The open-source @apollo/gateway is functionally abandoned in favour of their Rust-based router, and a meaningful list of features is behind an enterprise agreement. I’m keeping an eye on alternatives like Hive.

Libraries

Prisma

About eighteen months on Prisma, mostly good. The tooling around migrations and schema management is well thought through, and the type safety is the best I’ve used — query results know which relations were selected and reflect that in the type. Before Prisma I was on TypeORM, which is also solid and in some ways generates better SQL.

Two pain points worth flagging. Prisma ships its own Rust query engine that mediates between Node and the database. In theory fine; in practice I’ve watched it issue many consecutive queries where a single JOIN would have done the job. And I’ve spent more time than I’d like fighting the built-in connection pool — under load, queries start failing with no available connections, pgbouncer doesn’t really fix it, and the only reliable workaround is throwing a lot more application instances at the problem. I don’t see this with TypeORM.

Honourable mentions

clsx for class string building, pairs naturally with Tailwind. dataloader for batching, indispensable inside GraphQL to keep N+1 problems off your service. date-fns for date formatting and arithmetic. puppeteer for scraping and rendering PDFs.

Infrastructure

Digital Ocean

Digital Ocean has been the default for personal and freelance work for eight years. Less feature-rich than AWS — that’s the point. As a single developer across many projects, simplicity beats power. Their App Platform lets me hand infrastructure management to them on client work, which is worth the markup. I keep AWS in mind for the genuinely complex cases, but I haven’t hit one yet on a client project.

Vercel

Vercel has been an enjoyable addition for Next.js deployments. This is a space I’ll deliberately grow into more this year.

PostgreSQL

Still the favourite RDBMS. Default choice on anything new.

RabbitMQ

RabbitMQ is the message broker I reach for. Affordable to scale on CloudAMQP compared to managed Kafka, and the more sophisticated routing primitives open up cleaner asynchronous designs. Node SDKs are mature and the local docker-compose setup is a few lines.

Third-party tools

DataDog for logging and observability. SendGrid for transactional email — I used Mandrill in the past, but their DX hasn’t kept pace. GitHub for code and project management, after a long stretch on GitLab; Actions has overtaken GitLab CI/CD and the project management side has tightened up enough to consolidate. Unleash for feature flags, SaaS or self-hosted.

Software

DataGrip for databases, by a wide margin the best tool I’ve used in this space — DBeaver is fine for general use but DataGrip is a few tiers above. WebStorm for code, recently swapped over from years on Visual Studio Code; the IDE feels more mature and the day-to-day is more pleasant. PHPStorm for the PHP work that survives. Lens for Kubernetes clusters. Postman for tracking and exercising APIs.


That’s the stack. If it’s useful for anyone weighing up a new project or trying to land on a coherent set of tools, take what’s useful and leave the rest.

Comments