Introducing Nulvless: authentication, authorization and edge functions for SaaS
Authentication, authorization, communications and edge functions for SaaS, in one platform you configure per environment.

On this page
Every SaaS ends up building the same thing before it builds anything else: a sign-up form, a password reset email, a second factor, an invitation flow, a role check on every route, and somewhere to see who signed in from where. None of it is the product, and all of it has to be right.
Nulvless is the platform we wanted to exist for that layer. This post explains what it is, what is in it today, and how it is meant to be used.
The problem with stitching it together
The usual answer is a stack of vendors: one for authentication, another for transactional email, a third for SMS, something for feature flags, and custom code for roles and permissions. Each piece works. The seams between them are where the bugs live.
A role is renamed in one place and not the other. The staging SMS provider gets promoted to production with test credentials. A session is revoked, but the email that confirms it never arrives because the template lives in a different tool. Nobody can answer "who changed this setting, and what was it before?" without asking around.
We built Nulvless so that the identity of a user, what they are allowed to do, the messages they receive and the code that runs on their requests all live in one model, with one history.
What is in the platform
Authentication
Password, passwordless, social providers, MFA, sessions and sudo mode.
Authorization
Scopes, roles and grants scoped to any resource of yours.
Communications
Email and SMS templates per channel and language.
Edge Functions
A Deno runtime with npm support, running next to every sign-in.
Observability
Traffic, performance and a queryable request trail.
OAuth Server
Your project as a standards-compliant issuer.
Underneath all of it is the Nulvless Network: requests land on the edge closest to your user, the session is verified there, and your Edge Functions run in the same place. A signed-in request does not cross an ocean to find out who sent it. Introducing Edge Functions explains how that works.
Environments from the first day
An environment in Nulvless is not a flag on a row. It is a full copy of the project, with its own users, sessions, providers, templates and keys, answering on its own issuer URL:
project · acme
├── main → acme.nulvless.co
├── staging → acme-staging.nulvless.co
└── develop → acme-develop.nulvless.coConfiguration moves between them only when you promote it, and a promotion
starts as a diff you read before anything is written. Data never moves. A test
user created in develop cannot appear in production, because it was never in
that store.
We wrote more about why in Why staging users can never reach production.
What it looks like in code
The SDK runs in the browser with a publishable key, and on your server with a secret one.
import { createClient } from '@nulvless/nulvless-js';
export const nulvless = createClient('https://acme.nulvless.co', 'pk-…');
const { data, error } = await nulvless.auth.signIn({
email: '[email protected]',
password,
});Pointing the same app at staging is a URL and a key change. Nothing else in your code moves. The quickstart takes you from an empty project to a signed-in user.
Where we are
Nulvless is in early access. The console, the SDK, the Nulvless Network and everything listed above are running, and we are onboarding teams in small groups so we can work closely with each of them. You can join the early access list from the console.
What this blog is for
We will use this blog for three things:
- Announcements when something new ships, alongside the changelog.
- Engineering posts about how the platform works underneath and the trade-offs we made.
- Guides that go further than the docs, from a blank project to something you would put in front of users.
If you want to start with something practical, read Add sign-in with MFA to a React app.
