> ## Documentation Index
> Fetch the complete documentation index at: https://getfloo.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Deploy an Express API with Postgres and sign-in

> Give a Node.js Express backend managed Postgres, invite-only sign-in, and a live URL with one config file and one command. No auth code and no row-level security policies to write.

An Express backend your agent wrote, live at `https://<app>-dev.getfloo.app` with managed Postgres and sign-in for your team. floo signs people in at its gateway and tells your code who they are in a request header, so the backend has no auth code, and the browser never talks to the database.

## Agent prompt

Paste into Claude Code, Codex, Cursor, or any agent that can run shell commands. Replace `orders-api` with your app name.

```text theme={null}
Deploy this Express app to floo with managed Postgres and invite-only sign-in. App name: orders-api.
1. Install the floo CLI if `floo --version` fails: curl -fsSL https://getfloo.com/install.sh | bash. Then run `floo auth login` and have me approve the sign-in.
2. Make the server listen on process.env.PORT on 0.0.0.0, call app.set("trust proxy", true), and add GET /health.
3. Add a Dockerfile and a .dockerignore (node_modules, .git, .env) following https://getfloo.com/docs/build/express.md.
4. Run `floo init orders-api`. In floo.app.toml set access_mode = "accounts" under [app], add [managed.default] with type = "postgres", and set migrate_command if the repo has a migration script.
5. Connect to Postgres with process.env.DATABASE_URL. Read the signed-in user from the x-floo-user-email header. Write no login code.
6. Run `floo preflight --json` and fix every error. Commit with git.
7. Run `floo deploy --json` and report the live URL.
```

## The files

```js server.js theme={null}
import express from "express";
import pg from "pg";

const pool = new pg.Pool({ connectionString: process.env.DATABASE_URL, max: 10 });

const app = express();
app.set("trust proxy", true);
app.use(express.json());

app.get("/health", (_req, res) => res.send("ok"));

// floo's gateway signed this person in and set the header.
app.get("/api/orders", async (req, res) => {
  const email = req.get("x-floo-user-email");
  const { rows } = await pool.query(
    "select id, item, quantity from orders where created_by = $1 order by id desc",
    [email],
  );
  res.json(rows);
});

app.post("/api/orders", async (req, res) => {
  const email = req.get("x-floo-user-email");
  const { item, quantity } = req.body;
  const { rows } = await pool.query(
    "insert into orders (item, quantity, created_by) values ($1, $2, $3) returning id",
    [item, quantity, email],
  );
  res.status(201).json(rows[0]);
});

const port = Number(process.env.PORT ?? 3000);
app.listen(port, "0.0.0.0", () => console.log(`listening on ${port}`));
```

```toml floo.app.toml theme={null}
[app]
name = "orders-api"
access_mode = "accounts"

[services.web]
type = "web"
path = "."
port = 3000
ingress = "public"
dev_command = "node --watch server.js"
migrate_command = "node scripts/migrate.js"

[managed.default]
type = "postgres"
```

The Dockerfile is the two-stage `node:22-slim` one in the [Express guide](https://getfloo.com/docs/build/express.md#1-add-a-dockerfile). `migrate_command` runs with the new image before traffic moves to it; a failed migration stops the deploy and the previous version keeps serving. The examples use ESM, so `package.json` needs `"type": "module"`.

## Deploy

```bash theme={null}
floo preflight
git add -A && git commit -m "Deploy to floo"
floo deploy
```

The first run creates a floo-hosted project and its dev database. Later runs push the new commit. See [Deploy without a GitHub repository](https://getfloo.com/docs/deploy/without-github.md) for what each run does, or [connect your own GitHub repository](https://getfloo.com/docs/build/express.md#4-connect-the-repo-and-deploy) instead.

## Why there are no row-level security policies

Backends that let the browser query the database need a correct row-level security policy on every table, or the data is readable with the public key. Here the browser only talks to your Express routes, every request passes floo's gateway first, and only your server holds `DATABASE_URL`. Who can see which rows is the `where created_by = $1` in your own code, which your agent can test and you can review.

## Let an agent call the API

To let a script or another agent call `/api/*` without a browser session, declare which routes accept keys and create a key for it. It is scoped, rate-limited, and revocable on its own. See [App API keys](https://getfloo.com/docs/guides/app-api-keys.md).

## Verify

```bash theme={null}
floo deploys status --app orders-api --json
floo db schema --app orders-api
curl -i https://orders-api-dev.getfloo.app/health
```

A `401` or a redirect to sign-in from `curl` means the app is up and sign-in is working. Invite people with `floo apps invite <email> --app orders-api`.

## Next steps

> [card] [Build an Express app](https://getfloo.com/docs/build/express.md)
>
> Dockerfile, storage, custom domain, and local dev with real credentials.

> [card] [Postgres](https://getfloo.com/docs/guides/postgres.md)
>
> Injected variables, pgvector, preview branches, and migrations.

> [card] [Cron jobs](https://getfloo.com/docs/guides/cron-jobs.md)
>
> Run a script on a schedule in the same image.

> [card] [floo deploy](https://getfloo.com/docs/cli/deploy.md)
>
> Every flag and error code.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.