DEV Community

GALIH Putro
GALIH Putro

Posted on Originally published at Medium on

Why I Chose Better Auth Over NextAuth, Clerk, and Auth0, And Why You Might Too

Authentication libraries are everywhere. Most of them slow you down. Better Auth speeds you up.

Better Auth Banner

Looking at Auth.js/NextAuth, Clerk, Auth0, and others? Here’s why Better Auth stands out:

Key Advantages of Better Auth

1. Total Control Over Your Data & Database

Better Auth uses adapters like Prisma, Drizzle, or Kysely and auto-generates DB schemas , giving you full ownership of user data while maintaining type safety and seamless migrations.

Contrast that with Auth0 or Clerk, your data lives in their cloud, limiting flexibility and lock‑in.

2. Smooth Email + Password + OAuth Setup

Better Auth supports credentials (email/password) out of the box — no wrestling with CredentialProvider quirks like in Auth.js, which many developers find frustrating

3. Plugin Ecosystem for a Clean, Extendable Core

It’s built with an official plugin architecture (teams, MFA, magic links, rate limiting, audit logging, organizations), so you get lightweight core logic plus opt-in features.

4. Modern Developer-Friendly Design

Designed TypeScript-first, with clear API and intuitive integration across React, SvelteKit, Next.js, even Express. Reddit

5. Open Source Freedom

Licensed MIT, you fully control updates and deployment. No unexpected breaking changes or access throttles.

Banner

How It Works

Using Better-Auth is refreshingly simple. Here’s what a basic setup might look like with prisma:

import { betterAuth } from "better-auth";
import { prismaAdapter } from "better-auth/adapters/prisma";
import { PrismaClient } from "@/generated/prisma";

const prisma = new PrismaClient();
export const auth = betterAuth({
    database: prismaAdapter(prisma, {
        provider: "postgresql",
    }),
});
Enter fullscreen mode Exit fullscreen mode

Implementing RBAC with Better Auth

Here’s how to define permissions, create roles, and enforce access control cleanly in Better Auth :

import { createAccessControl } from "better-auth/plugins/access";

// 1. Define permission statements for each resource
export const statement = {
  project: ["create", "share", "update", "delete"], // available actions
} as const;

// 2. Initialize access control with your permission schema
const ac = createAccessControl(statement);

// 3. Create named roles with explicit permissions
export const user = ac.newRole({
  project: ["create"],
});

export const admin = ac.newRole({
  project: ["create", "update"],
});

export const myCustomRole = ac.newRole({
  project: ["create", "update", "delete"],
  user: ["ban"],
});

// Pass roles and permissions to the plugin
export const auth = betterAuth({
    plugins: [
        ...
        adminPlugin({
            ac,
            roles: {
                admin,
                user,
                myCustomRole
            }
        }),
    ],
});
Enter fullscreen mode Exit fullscreen mode

How It Works: Clean, Declarative, and Type-Safe

  • statement defines full permission sets per resource (e.g. project permissions include create, share, update, delete).
  • createAccessControl(...) builds a control engine enforcing these actions.
  • newRole({...}) creates permission bundles such as user, admin, and myCustomRole—each restricted only to allowed actions.
  • Roles are literal types, and permissions are strictly typed via as const.

Extending RBAC: Client-Side Permission Checks with hasPermission

Once you’ve defined roles server-side via Better Auth’s access control plugin, you can also check permissions in your client application — ideal for pre-flight UI logic or action gating.

// Example Usage on client
const canCreateProject = await authClient.admin.hasPermission({
  permissions: {
    project: ["create"],
  },
});

// Checking multiple resources in one call
const canCreateProjectAndUpdateSale = await authClient.admin.hasPermission({
  permissions: {
    project: ["create"],
    sale: ["update"],
  },
});
Enter fullscreen mode Exit fullscreen mode

When to Choose Better Auth

Choose Better Auth if you:

  • Want complete control over your user database.
  • Need reliable email/password login without the complexity.
  • Appreciate plugin-based extensibility for teams, 2FA, roles, etc.
  • Prefer a TypeScript-first, cross-framework design.
  • Want to avoid vendor lock-in and recurring costs.

Ready to Take It Further?

If you’re looking for:

  • A full boilerplate (Express + Better Auth + Joi/Zod + admin UI),
  • A migration guide from other auth systems (like NextAuth),
  • Or custom plugin development for features like ABAC, magic links, or role-management workflows

Then you need to try better-auth! Let me know if you’d like any of those 🚀

Top comments (0)