See-sawing State of Web Dev

See-sawing State of Web Dev

Why does it always seem like we web devs can't make up our mind? Let me explain...

Here's a summary of what hip new tech a web startup would likely build their business around, depending on the time period,

~2008–2010

What I remember my dad's old desktop to look like in 2010

🎨 🔀 Rendering + Routing - Server-side (MPAs)

🔌 API paradigm - RPCs + SOAP (declining) + REST (rising)

🗃️ Popular DB model - Relational (MySQL)

🌐 Hosting - On-premise servers running open-source Linux (bare metal)

🌟 Popular Technologies/Frameworks: LAMP, Elixir, jQuery

~2016–2018

🎨 🔀 Rendering + Routing - Client-side (SPAs) w/ AJAX requests

🗃️ Popular DB model - Non-Relational (MongoDB, DynamoDB, Firebase)

🔌 API paradigm - GraphQL + REST (Still going strong)

🌐 Hosting - Close-sourced, fully-managed cloud services (Netlify, AWS, Firebase)

🌟 Popular Technologies/Frameworks: MERN, MEAN, Gatsby.js + Apollo, Firebase

~2023–2024

Technically from 2020 but still an iconic Craig Federighi moment

🎨 🔀 Rendering + Routing - Server-side (App router + React Server Components)

🗃️ Popular DB model - Relational (Postgres, SQLite in embedded/local-first architectures)

🔌 API paradigm - tRPC + Edge Functions + REST (Still going strong)

🌐 Hosting - Self-hosted on VPSs and "bare metal"

🌟 Popular Technologies/Frameworks: Next.js, Astro, Remix


Did we all just collectively take a massive u-turn in the last 15 years?

Oh, and just when we thought we'd finally reached web-dev nirvana, a fresh buzz around "local-first" architectures, zero-latency apps running proxy databases right inside your browser, has entered the chat, swinging the pendulum towards the client side even more.

Meanwhile, cloud services are staging their comeback too with Neon, Supabase, Convex, Clerk, and PostHog gaining a lot of traction.

So, are we stuck in this see-saw forever, trading good engineering sense for shiny new toys?

Not quite. We're actually witnessing convergence: each new wave selectively keeps the best features from the last, fine-tuning what came before. Sure, we sometimes swing too far, but that's just part of iterating towards something better.

Admittedly, I've exaggerated this tech timeline a bit, conveniently skipping over details like Supabase or Convex being fully self-hostable, to express the perspective of a slightly jaded engineer who's watched countless trends threaten years spent perfecting his stack. On some days, I'm that jaded engineer too when my optimism doesn't get the best of me.

Let's break these trends down,

⚛︎ Rendering & UX: RSC + Client Capabilities

TanStack has come up with a serious contender in the absence of remix with TanStack Start

What once was a matter of dogma has become that of choice. Within the same project in the same framework, you can segment your code conveniently to decide what runs on the client vs the server.

If you call a server function on the server side, it acts as a regular function. On the client side, it acts as an API endpoint. This way, you can fetch your data, render your component fully and once it reaches the client, can poll the same function, perform mutations to the data, etc. How handy!

💡 Tools like Remix and Next.js leverage “render‑as‑you‑fetch” patterns to pre‑fetch/prerender content ahead of hydration, marrying SEO‑friendly server‑rendering with SPA‑like snappiness. Again, tending towards best of both worlds! :D

🔗 API Evolution: tRPC, GraphQL & Request Batching

tRPC adopted GraphQL‑style request batching, cleverly using httpBatchLink to bundle all HTTP requests fired within ~1ms of each other into one request for performance with simple configuration.

Crucially, unlike GraphQL, it avoids open, unguarded queries: every procedure lives behind an endpoint with end‑to‑end TypeScript safety. Although GraphQL had provided a layer of type safety for server-client communication, it came in through an unwieldy code-gen step.

In tRPC, types are defined once and enforced universally through TS's own inference rules. You never have to leave TS.

Not only did it extend GraphQL's strengths, it also prevented accidental over‑fetching and insecure operations that could be performed by novice developers. Simply adding a new key to the query could risk exposing sensitive data or even tanking the server CPU if the backend developer wasn't too careful.

💡 We now have the backend control of traditional REST with the quality-of-life benefits of GraphQL. Another case of convergence after an initial overcorrection.

📦 Monorepos vs Microservices vs Monoliths

Nrwl's Nx and Vercel's Turborepo are the two big contenders in the game. One provides you with all the tooling you'll ever need for managing large projects, the other is minimalistic and works quietly behind the scenes.

Monorepos often sound like monoliths but they actually preserve microservice modularity. You get atomic commits, shared pipelines, unified standards, and shared UI libraries; all the benefits of microservices plus code reuse, easy cross‑project refactors, and visibility across modules.

💡Yet again, best of both worlds!

🗃️ Data Storage: MongoDB (+ Firebase) → Postgres (+ Supabase)

MongoDB (and Firebase) triumphed initially by removing schema constraints, letting developers prototype quickly without joins or migrations. But as startups scaled, this looseness morphed into tech debt, cruft, and unpredictable behaviors.

Postgres re‑entered as a stabilizing force, while offering JSONB to reclaim flexible document‑style storage with full indexing and query support. This coincided with the rise of LLMs that required vector databases to serve as their "memory" and Postgres's pgVector extension seemed to be at the right place at the right time.

💡 Here, we see developers opting for flexibility as they originally did with MongoDB, but with added reliability, the ability to isolate DB and API logic and capabilities at handling emerging markets. Flexibility surely took a slight hit, especially due to how easy MongoDB was to set up as a distributed storage, but the tradeoffs were still a net positive.

Supabase emerged as an open‑source, self‑hostable Firebase replacement built atop Postgres. It preserves real‑time APIs, edge functions, self-hosting and even exportability with zero lock-in.

💡 We see Supabase as a direct response to Firebase. Developers wanted a backend that "handled it all" like Firebase but also wished to not be vendor-locked into paying expensive cloud fees. Further, we wanted a backend that's reliable (like a certain ACID compliant DB) and doesn't treat row-level security as a second-class citizen.

🔌 Hosting: On‑Prem → Cloud → DIY VPS + Coolify (?)

Hmmmm, is Hostinger trying to divide the self-hosting community here?

In early years, secure hosting meant physical control on company servers. Then AWS and others democratized the cloud with managed services, CI/CD, scalability, and pay‑as‑you‑go pricing. More recently, rising cloud costs and billing shocks (like waking up to a $10K bill) spurred projects like Coolify, built atop Docker Compose, to let you self‑host on your own VPS easily and cheaply while keeping full control and cutting recurring costs.

💡 Again, still retaining the convenience of not having to manage your own hardware in a number of geolocations AND not worrying about setting up services from scratch while also saving money! 😄

Important Sidenote: While I've only used Coolify to run my personal VPS and haven't met anyone who uses it at work, I reckon it and it's competitors like Dokploy, Dokku, etc. will eventually start to break through the enterprise barrier.

🔮 What’s Next: The Emerging Wave as We Iron Out the Deficiencies

Every new trend attempts to plug the gaps created by the previous trend.

So, in order to take a stab at this, let's try to identify what the last-gen did better than current-gen technology.

Decision overhead due to RSCs

To "use client" or not to "use client", that is the question.

With the ability to make DB queries directly inside your component came the drawback of having to silo server logic with client-side interactivity into separate components.

The way forward could be through "dimorphic hooks" i.e. hooks that act as pure functions on the server-side and hooks on the client-side. If you have an idea for how we could remedy this as well, feel free to share it!

Siloed Monorepos

Monorepos, while extremely powerful and optimized, can still result in bloated diffs due to multiple independent teams constantly pushing code. Perhaps the next gen of monorepos might extend Git in some way - like Jujutsu - to better isolate code diffs.

All things considered, despite their presence for a long period, the world of monorepos is a bit of a wild west where you have Turborepo, which stays out of your way, to Nx, which allows you to control everything in your monorepo.

Horizontally scaling Postgres

Supabase has an excellent writeup on Supavisor from which I stole this visual. Do check it out!

Although tools do exist that make it possible to horizontally scale your Postgres DB with their tradeoffs (Citus, Yugabyte, CockroachDB), it doesn't compare to the seamless experience you'd find creating a distributed DB with MongoDB & Cassandra.

This is almost by design as its ACID properties value reliability over all. Maybe the next iteration will present a solution that provides the reliability and API agnostic model of Postgres combined with easy data partitioning? This will be an exciting development to watch!

Cloud Reliability

Despite self-hosting's attractiveness for cost saving and data ownership, cloud services are still preferred by large scale businesses and enterprise due to their incredibly high availability with almost zero ops overhead.

While working for government entities, we often set up a hybrid model for their infra where we'd use cloud providers for load balancers, CDN, etc. but would host all sensitive services like CMS, CRM, portals and databases on a self-managed VM. Perhaps the wider adoption for this model is the future?


🤔 What are your thoughts? What could mark the next trend in web dev? Local AI-model powered linters? Transpiling all backend code to Rust for 10x performance?

To view or add a comment, sign in

Others also viewed

Explore topics