Skip to main content

Launch a SaaS Starter

The saas-starter stack stands up a complete SaaS backend in one launch. You get a managed PostgreSQL database, a Directus data studio and content API attached to it, end-user authentication you can point your own frontend at, an object-storage bucket for assets and user uploads, and all of it served on a custom edge domain with a certificate the platform provisions for you.

It is the plumbing every product needs on day one, wired together and EU-resident before it reaches the Running state.

What it is, and who it is for

A SaaS backend kit is the layer that sits between your customers and your data: a place to store and model that data, an admin studio for your team, an API your frontend calls, a way for end users to sign in, somewhere to put their files, and a domain to serve it all from. The saas-starter stack gives you every one of those pieces, already connected:

  • A data studio and content API. Directus turns your PostgreSQL into an editable backend with a polished admin app plus instant REST and GraphQL endpoints over every collection.
  • End-user auth. FoundryDB auth-as-a-service runs as an OIDC issuer your own frontend signs users into. You do not build login, sessions, or token issuance yourself.
  • Object storage. A Files bucket for product assets, customer uploads, and exports, attached to the app so uploads land in it automatically.
  • Your own domain. A custom edge domain with an auto-provisioned certificate, so the backend is reachable at a clean hostname over HTTPS from the moment it is Running.

This stack is for teams who want to ship a product, not assemble infrastructure:

  • Founders and small teams who need a backend, an admin tool, auth, storage, and a domain on the first afternoon, not the first sprint.
  • Developers prototyping a SaaS who want REST and GraphQL over PostgreSQL plus sign-in and uploads without writing any of it by hand.
  • Anyone who needs their product data, identities, and files to stay in their own EU-resident services rather than a third-party platform.

Composition

The stack composes three FoundryDB primitives, wired together at launch:

ResourceKindWhat it isWhy it is here
dbdatabaseManaged PostgreSQL 17 (tier-1, 25 GB standard storage)The durable home for your product data. Directus uses it as its backing store, and you own it directly.
storagefilesAn object-storage bucket (10 GB soft quota)Holds assets and end-user uploads. Attached to the app so file fields and uploads write straight to it.
appappA hosted Directus application, attached to db and storage, fronted by end-user auth and a custom edge domainThe admin studio plus the REST and GraphQL content API. Auth gives your frontend an OIDC sign-in flow; the edge domain serves it all over HTTPS.

The app depends on both db and storage, so the platform brings the database and bucket up first, then provisions and wires the app last.

How it differs from the plain cms stack

The cms stack is the same Directus-on-PostgreSQL core: a database and a Directus app. The saas-starter stack is that core plus the three things a real product needs around it:

  • An attached Files bucket, so uploads and assets have somewhere to live instead of going into ephemeral container storage.
  • End-user auth as an OIDC issuer, so your own frontend has a sign-in flow without you building identity from scratch.
  • A custom edge domain with an auto-provisioned certificate, so the backend is served on a clean HTTPS hostname rather than a default app URL.

If you only need an editable content backend, launch cms. If you are building a product that has customers, files, and a front end, launch saas-starter.

saas-starter stack composition & launch
RUNNING Stack wired · SaaS backend live · EU
Stack Templatesaas-starterlaunch ⇉PostgreSQLDATABASE_URL → appFilesS3 creds → appDirectusadmin + REST / GraphQLEnd-user AuthOIDC issuerfront →Edge DomainTLS · auto certserve →SaaS BackendEU-resident
Template · launchPostgreSQLFiles bucketDirectus (SaaS backend)End-user auth (OIDC)Custom edge domainwiring (env injected)

Prerequisites

The saas-starter stack does not include an inference resource, so you do not need a configured inference provider to launch it.

Export your token for the commands below:

export FOUNDRYDB_TOKEN="your-api-token"

Launch it

You can launch from the console with one click, or drive the same flow over the API.

Option A: one-click in the console

Open the Stacks catalog in the console, pick Launch a SaaS starter, review the cost preview, and click Launch. The console runs the same preview, accept, and launch flow described below and shows the live endpoint once the stack reaches Running.

Option B: the API

The launch is a two-step flow: preview the cost first, then send the launch request with the cost you accepted. This guarantees you always see an up-to-date estimate before any billable resource is created.

1. Preview the cost

curl -X POST https://api.foundrydb.com/stacks/preview \
-H "Authorization: Bearer $FOUNDRYDB_TOKEN" \
-H "Content-Type: application/json" \
-d '{"template_name": "saas-starter"}'

The response breaks the cost down per resource:

{
"template_name": "saas-starter",
"currency": "EUR",
"monthly_total": 61.00,
"line_items": [
{
"symbolic_name": "db",
"kind": "database",
"description": "PostgreSQL tier-1 + 25 GB standard storage",
"monthly_cost": 28.00,
"is_ceiling": false
},
{
"symbolic_name": "storage",
"kind": "files",
"description": "Files bucket, 10 GB soft quota",
"monthly_cost": 5.00,
"is_ceiling": false
},
{
"symbolic_name": "app",
"kind": "app",
"description": "Directus app tier-1 + 10 GB storage, end-user auth, edge domain",
"monthly_cost": 28.00,
"is_ceiling": false
}
],
"warnings": []
}

monthly_total is the figure you pass to the launch request. The cost preview is computed fresh on every call, so always preview right before launching.

2. Accept and launch

Pass the monthly_total from the preview as accepted_monthly_cost:

curl -X POST https://api.foundrydb.com/stacks \
-H "Authorization: Bearer $FOUNDRYDB_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "my-saas",
"template_name": "saas-starter",
"accepted_monthly_cost": 61.00
}'

The response is 201 Created with the stack in Pending status. Capture its id:

export STACK_ID="the-id-from-the-response"

If accepted_monthly_cost has drifted from the current estimate by more than EUR 0.01, the launch returns 409 Conflict and you re-preview. If it is omitted entirely, the launch returns 400 Bad Request.

3. Poll for status

The stack provisions asynchronously. Poll GET /stacks/{id} until status reaches Running:

curl https://api.foundrydb.com/stacks/$STACK_ID \
-H "Authorization: Bearer $FOUNDRYDB_TOKEN"

Typical progression is Pending then Provisioning then Wiring then Running. Most stacks complete within a few minutes. Once the stack is Running, the endpoint_url field carries the live Directus URL on your custom edge domain:

{
"id": "...",
"name": "my-saas",
"status": "Running",
"endpoint_url": "https://my-saas-app.foundrydb.com",
"resources": [
{ "symbolic_name": "db", "kind": "database", "status": "Running", "service_id": "..." },
{ "symbolic_name": "storage", "kind": "files", "status": "Running", "service_id": "..." },
{ "symbolic_name": "app", "kind": "app", "status": "Running", "service_id": "..." }
]
}

First run

Once the stack is Running, everything below is already wired. You do not paste a connection string, an access key, or an issuer URL anywhere.

Open the Directus studio and sign in

Open the endpoint_url in a browser. It is a real foundrydb.com edge hostname with a valid certificate, and Directus serves its admin app there. On first start Directus creates an initial administrator account. Retrieve the generated admin credentials from the app resource:

curl https://api.foundrydb.com/stacks/$STACK_ID \
-H "Authorization: Bearer $FOUNDRYDB_TOKEN" | jq '.resources[] | select(.symbolic_name=="app")'

Sign in with the admin email and password, then change the password from Settings once you are in. This admin account is for your team operating the studio; it is distinct from the end-user auth below, which is for your product's customers.

Define a collection

In the studio, create a collection (Directus calls a table a collection). Go to Settings, then Data Model, then Create Collection. Name it projects and add a couple of fields, for example a name string and an owner string. Save, then add a few items under Content. That collection is a real table in your PostgreSQL db resource the moment you save it.

Hit the auto-generated content API

Directus exposes every collection over REST and GraphQL with no extra work. Create an access token in the studio under your user profile, then query the REST endpoint on your edge domain:

curl "https://my-saas-app.foundrydb.com/items/projects" \
-H "Authorization: Bearer <directus-access-token>"
{
"data": [
{ "id": 1, "name": "First project", "owner": "ada" },
{ "id": 2, "name": "Second project", "owner": "grace" }
]
}

The same data is available over GraphQL at the /graphql path on the same host. This is the content API your product's frontend consumes.

Wire your frontend to end-user auth

The app launched with FoundryDB end-user auth enabled, which runs as a standards-compliant OIDC issuer for your product. Your own frontend points its OIDC client at the issuer to sign customers in; you do not build login, sessions, or token issuance. Retrieve the issuer URL for the app:

curl https://api.foundrydb.com/stacks/$STACK_ID/auth \
-H "Authorization: Bearer $FOUNDRYDB_TOKEN"

The response carries the issuer_url (and its /.well-known/openid-configuration discovery document) that your frontend's OIDC library uses for sign-in, token exchange, and validation. See Enable Auth and Integrate Auth for the full client setup, including the authorization-code flow and how to validate tokens on your own API.

Upload an asset to the bucket

The storage bucket is attached to the app, so file fields and uploads in Directus write straight into it. In the studio, add a file field to a collection or upload through the Files area, and the object lands in your storage resource. You can also reach the same bucket directly with its S3-compatible credentials for server-side uploads and exports. See Attach Files to Apps and Using S3 for the bucket's endpoint, keys, and the S3 API surface.

How the wiring works

The stack engine does not introduce a new provisioning path. It calls the same APIs you would call yourself, in dependency order, and injects the configuration each resource needs to reach the others.

For the saas-starter stack:

  1. The db resource is provisioned first: a managed PostgreSQL 17 service.
  2. The storage resource is provisioned: an object-storage bucket with a 10 GB soft quota.
  3. The app resource is provisioned and attached to both. During the Wiring phase, the engine injects the database connection string into the Directus app as DATABASE_URL, and the bucket's S3 credentials as the S3_* environment variables. Because the app is attached to exactly one database and one bucket, this injection is automatic.
  4. End-user auth is enabled on the app, standing up an OIDC issuer your frontend signs customers into.
  5. The custom edge domain is provisioned with an auto-issued certificate, so the app is served over HTTPS on a clean hostname.

There is no connection string to copy, no S3 key to paste, no issuer URL to configure by hand, and no certificate to request. By the time the stack reaches Running, Directus already knows where its database and bucket are, the auth issuer is live, and the edge domain resolves over HTTPS.

Cost and EU residency

The saas-starter stack costs the sum of its resources, shown in your cost preview at launch: a tier-1 PostgreSQL database, a Files bucket, and a tier-1 Directus app with auth and an edge domain. The figures above are illustrative; the preview endpoint returns the current numbers. Each child resource is an ordinary service in your account, billed through your normal plan, and you can scale any of them individually after launch.

Every resource is EU-resident. The PostgreSQL database, the Files bucket, the Directus app, the auth issuer, and the traffic between them all stay within the platform's European footprint. Residency is not a setting you remember to flip; it is where the platform runs.

Teardown

Delete the whole stack with one call:

curl -X DELETE https://api.foundrydb.com/stacks/$STACK_ID \
-H "Authorization: Bearer $FOUNDRYDB_TOKEN"

Returns 202 Accepted. The reconciler deletes the app first, then the bucket and the database, in reverse dependency order. Teardown is atomic and leaves no orphaned database, bucket, or app behind. It is irreversible, so export anything you want to keep first.

Next steps