Skip to early access
MemoLane

Why we chose Elysia for our backend

Elysia

Why we chose Elysia for our backend

Memolane started on Go. That's still true. The platform layer - user provisioning, ops tooling, email infrastructure - all of it runs on Go services. Go is excellent for that kind of work: straightforward concurrency, small binaries, predictable behavior under load. We're not replacing any of that.

But for the consumer product - the journaling app, the recall system, the review flows - we made a different call. We went full TypeScript. And within that TypeScript world, Elysia is our backend framework.

Here's why.


The context-switching problem

We're a small team. That means the same two or three people are working on the Go platform code and the consumer product and the mobile app. When you're switching between Go and TypeScript dozens of times a day, something always falls through the cracks.

It's not that either language is bad. It's that the mental overhead adds up. Different idioms, different error handling patterns, different ways of thinking about types. By the end of a long day, you start making mistakes at the seams - usually in the API contract between services.

For the consumer product specifically, we wanted a single language across the stack. TypeScript made sense: we're already writing it for Next.js on the web and Expo on mobile. Adding a Go service for every new feature meant another mental context switch for every new endpoint.


Why not Express, Fastify, or Hono?

We looked at all of them.

Express is a classic, but it's showing its age. No native TypeScript, validation is bolted on, and the types you get from @types/express feel like an afterthought. You spend a lot of time wiring things together that should just work.

Fastify is genuinely good. Fast, schema-first, well-maintained. But the schema validation story - JSON Schema, then zod adapters, then serialization - felt like a lot of ceremony for what we needed.

Hono we seriously considered. It's fast, runs on everything, has solid TypeScript support. If we were building an edge-first product, we'd probably be on Hono today.

But we landed on Elysia.


What Elysia gets right

The thing that clicked for us was end-to-end type safety with almost no ceremony.

const app = new Elysia()
  .post("/entries", ({ body }) => {
    // body is fully typed - no assertion needed
    return createEntry(body);
  }, {
    body: t.Object({
      content: t.String(),
      mood: t.Optional(t.Number()),
    })
  })

The schema you define for validation is the same schema that types your handler. There's no gap between "what I said the API accepts" and "what TypeScript thinks the API accepts." That gap is where bugs live, and Elysia closes it.

The ergonomics also feel right. It reads like Express - familiar enough that any backend developer can pick it up - but the defaults are sane and modern. Async everywhere, proper error handling, plugin system that doesn't fight you.


Bun as the runtime

Bun

Elysia is built to run on Bun, which is its own thing worth mentioning.

Bun as a package manager alone would have been worth the switch. If you've spent time staring at npm install progress bars, you know what I mean. Cold installs in our CI pipeline dropped from around 90 seconds to under 15.

But it's more than install speed. Bun runs TypeScript natively - no build step for local development, no ts-node, no esbuild wrapper. You write a .ts file and run it. The runtime is also genuinely fast; we're seeing response times in the low single-digit milliseconds for simple read operations.

The built-in test runner is a nice bonus. We removed Jest from the backend packages entirely. One less dependency, one less config file, tests that run noticeably faster.


The full product stack

For reference, here's what the consumer product runs on:

  • Web: Next.js (App Router)
  • Mobile: Expo
  • Backend: Elysia on Bun
  • Database: PostgreSQL (primary store)
  • Cache / queues: Redis
  • Monorepo: Turborepo

Go

The platform layer - the part users don't directly touch - stays on Go. That's not changing. Go is the right tool for long-running services, high-throughput pipelines, and the kind of systems code where you want zero surprises.

But for the consumer-facing API, Elysia and Bun have been solid. The development experience is better than anything we've tried before in this space.


Turborepo across the board

One more thing worth mentioning: the whole codebase lives in a single monorepo managed by Turborepo.

Shared TypeScript types between the Next.js app, the Elysia backend, and the Expo mobile app. No more copy-pasting interface definitions across three repos. No more "which version of the type is correct?" in code review.

Turborepo's incremental builds mean we're only rebuilding what changed. In a monorepo this size, that matters.


Building in public

We're sharing these decisions as we make them because we think the stack conversation in the TypeScript ecosystem is genuinely interesting right now. Elysia and Bun are newer, and there aren't that many production case studies yet.

If you're making similar choices, or if you've gone a different direction and have strong opinions about it, we'd like to hear from you. Find us on X at @NeoLabsHQ.

More posts coming as we ship.