Skip to content

a scalable stack for modern web developers in 2025


<- return to blog

Vue, Bun & Elixir

A scalable, fast, killer modern tech stack for 2025


If you're building a modern web app in 2025 you need a stack that’s fast, scalable, and easy to work with. The days of bloated monolithic frameworks are behind us. Instead this stack uses specialized tools that get the job done efficiently.

Vue, Bun, and Elixir — a powerful trifecta that combines a lightweight frontend, a fast and scalable backend for APIs, and a highly concurrent WebSocket server. This stack gives you speed, flexibility, and most importantly of all - developer joy.

Why not a monolith or server-side-components?

It's simple - speed and scalability. A monolith or server-side-components will never be able to match the speed of a statically served Vue bundle from NGINX or Caddy. It's more efficient for our backend to only serve a JSON REST API or WebSocket that our statically served client can consume.

Vue.js & TypeScript for the front-end


We are going to build our front-end using Vue.js and TypeScript, and we are going to make it a single-page-application that takes advantage of lazy-loading and code-splitting. This ensures we can statically serve our entire app while keeping initial bundle size low.

Vue is a simple front-end framework - it has a wonderful DX and is lightweight and fast. It has a simple learning curve that allows you to build more with less time.

Quasar, a component library for Vue makes it simple to create amazing apps.

Vue Component Example (Composition API)

<script setup>
  import { ref } from 'vue'
  const count = ref(0)
</script>

<template>
  <button @click="count++">Count is: {{ count }}</button>
</template>

<style scoped>
  button {
    font-weight: bold;
  }
</style>

Why not React?

Vue.js was chosen because it simply provides us less headaches and lets us focus on the fun part - building the app. I'm also firmly convinced that people who like JSX are masochistic freaks, because there is no other way to describe people who think it's OK to put your markup in a JavaScript function.

In Vue, larger components or pages can highly benefit from being separated into separate CSS, TS and Vue files using the options API. Smaller and more simple components can benefit as single-file-components using the composition API.

State management in Vue is simple with Pinia.

Vue embraces web standards like HTML, CSS, and the DOM, while React replaces them with abstractions.

React’s Problem: React’s Virtual DOM re-renders entire components unnecessarily unless you manually optimize it (useMemo, useCallback). Hooks in React introduce unintuitive rules, require useEffect for side effects, and lead to "stale closure" bugs. CSS in JS adds runtime overhead.

Vue reactively updates only what's needed. There is also no need for useState or useEffect.

Bun, Elysia & Prisma for REST APIs


Bun, Elysia & Prisma makes for a powerful and minimalistic stack for building REST APIs that are fast, typed, and efficient.

Bun is an all-in-one TypeScript runtime that’s fast, modern, and built from scratch in Zig.

Bun uses the event loop model of JavaScript, which is very good at handling I/O-bound tasks - perfect for APIs.

Elysia is a framework built on top of Bun, providing a fast, flexible, and end-to-end type-safe environment for building APIs.

Elysia Minimal Example

import { Elysia } from 'elysia'

new Elysia()
    .get('/', 'Hello World')
    .listen(3000)

Prisma is a modern, type-safe ORM for TypeScript that lets you interact with your database using auto-generated queries instead of raw SQL.

Bun is great at doing image manipulation using sharp for endpoints where users need to upload avatars or other images to an S3 bucket.

Bun also includes a websocket server that is useful for small projects on it's own. However, you won't get cool Elixir features like code hot-swapping, high concurrency or fault-tolerance that are useful at scale.

Why not Elixir for our REST JSON API?

Elixir is the wrong tool for the job. Elixir’s power lies in real-time systems and fault tolerance. Elixir has characteristics that can make it challenging to write the complex business logic that REST APIs can demand.

  • Lack of Object-Oriented structures
  • No return early pattern
  • Hard to avoid deep nesting of if, case, with statements
  • Pattern matching can get messy
  • Harder to find Elixir developers

Elixir was designed for concurrency, fault-tolerance and long-lived connections - not necessarily high-throughput, ultra-low-latency HTTP servers with short-lived connections.

Elixir for real-time features


So your front-end app happens to require real-time updates. Perhaps you have a dashboard that demands real-time data, or you want a live chat between your users.

We are going to use Elixir, Cowboy, Octo and Redis to build our real-time features.

Why Elixir?

Concurrency and fault-tolerance. Cowboy (Erlang’s HTTP server) efficiently handles WebSocket and SSE connections.

Elixir runs on BEAM, which supports millions of lightweight processes (not OS threads). Each WebSocket/SSE connection runs in its own process, isolated and crash-safe. Elixir can handle thousands to millions of concurrent connections.

Elixir also supports hot code swapping, meaning you can update code without restarting WebSocket/SSE connections for zero downtime deploys.

Erlang/Elixir is battle-tested when it comes to realtime features and is deployed in production by companies like Heroku, Discord and WhatsApp.

Building at Scale


If you're looking to build a web application or API that can handle high traffic, scale effectively, and offer a modern developer experience - the combination of Vue, Bun, and Elixir is an excellent choice.

This stack provides the speed, scalability, and flexibility required to support millions of users and can meet the demands of modern applications.

<- return to blog