Skip to content

Roles

Every Neon project starts with one owner role. Use Neon.Role to give your app, your migrations, and your teammates their own logins.

Pass the branch the role lives on:

const app = yield* Neon.Role("App", { branch });
app.roleName; // "myapp_app_dev_x7k2..."
app.password; // Redacted<string>

The generated name uses underscores, so it works unquoted in SQL. The password stays the same on every deploy and never prints in logs or plan output.

Set name when other code or SQL refers to the role:

const migrator = yield* Neon.Role("Migrator", { branch, name: "migrator" });

Changing name replaces the role. The old role is deleted and you get a new password.

Pass project instead of branch to put the role on the default branch:

const migrator = yield* Neon.Role("Migrator", { project, name: "migrator" });

Swap the role into the branch’s origin. Here it feeds Hyperdrive:

const origin = Output.all(branch.origin, app.roleName, app.password).pipe(
Output.map(([origin, user, password]) => ({ ...origin, user, password: password! })),
);
const hyperdrive = yield* Cloudflare.Hyperdrive.Connection("app-hyperdrive", { origin });

The host, port, and database come from the branch; the user and password come from the role.

Set noLogin for a role that owns objects but never connects:

const owner = yield* Neon.Role("Owner", {
branch,
name: "app_owner",
noLogin: true,
});

Its password is undefined. Grant it to login roles with SQL so they can act as it:

GRANT app_owner TO migrator;

Switching noLogin on or off replaces the role.

A role created in the console is refused until you adopt it:

const reporting = yield* Neon.Role("Reporting", {
project,
name: "reporting",
}).pipe(adopt(true));

reporting.password is the role’s current password. If Neon no longer stores it, the password is reset.