Launch a BI workspace
The bi-workspace stack stands up a full business-intelligence environment with one launch: a managed PostgreSQL database and a Metabase application, already wired together. You open one URL and you are building dashboards over a database you own, with nothing to connect by hand.
It is for anyone who wants charts, questions, and dashboards without standing up a BI tool, provisioning a database for it, and wiring a connection string between the two. Analysts, product teams, founders checking their own numbers, and engineers who would rather not run Metabase themselves all get the same outcome: a working workspace on infrastructure that is yours and resident in Europe.
What it composes
The stack creates two resources and connects them:
| Resource | What it is | Default spec |
|---|---|---|
db | A managed PostgreSQL 17 database. Metabase uses it as its own application database, and it is also browsable as a data source you can query. | tier-1, 25 GB standard storage |
app | A hosted Metabase application, attached to the database. | tier-1, 10 GB standard storage |
Metabase is an open-source BI tool: you write questions (saved queries), pivot them into charts, group those charts onto dashboards, and drop into a raw SQL explorer when you want full control. It needs a relational database to store its own state (your questions, dashboards, users, and settings), and it reads from one or more databases to answer those questions.
In this stack, the PostgreSQL service does both jobs. The launch injects the connection into Metabase so the database holds Metabase's application state and is registered as a queryable data source. Every dashboard you build persists into your own PostgreSQL, not into a black box.
Prerequisites
- An API token. See Authentication.
export FOUNDRYDB_TOKEN="your-token-here"
Unlike the rag-chatbot stack, bi-workspace does not include an inference resource, so you do not need an inference provider configured to launch it.
Launch it
Option A: the console
Open the Stacks catalog in the console, pick Launch a BI workspace, review the cost preview, and click launch. The console runs the same preview, accept, and launch flow described below and shows progress until the workspace is live.
Option B: the API
The launch is a two-step flow: preview the cost, then launch 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": "bi-workspace"}'
The response breaks the monthly cost down per resource:
{
"template_name": "bi-workspace",
"currency": "EUR",
"monthly_total": 138.00,
"line_items": [
{
"symbolic_name": "db",
"kind": "database",
"description": "PostgreSQL tier-1 + 25 GB standard storage",
"monthly_cost": 69.00,
"is_ceiling": false
},
{
"symbolic_name": "app",
"kind": "app",
"description": "Metabase app, tier-1 + 10 GB standard storage",
"monthly_cost": 69.00,
"is_ceiling": false
}
],
"warnings": []
}
monthly_total is the figure you pass to the launch request. The numbers above are illustrative; always read the live total from your own preview call, since plans and storage pricing change.
2. 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-bi-workspace",
"template_name": "bi-workspace",
"accepted_monthly_cost": 138.00
}'
The response is 201 Created with the stack in Pending status. Capture its id:
export STACK_ID="the-id-from-the-response"
If the accepted cost has drifted from the live estimate by more than €0.01, the launch returns 409 Conflict and you re-preview. If accepted_monthly_cost is omitted, it returns 400 Bad Request.
To launch with more resources, override a resource spec by its symbolic name and re-preview to get the new total:
curl -X POST https://api.foundrydb.com/stacks \
-H "Authorization: Bearer $FOUNDRYDB_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "my-bi-workspace-large",
"template_name": "bi-workspace",
"accepted_monthly_cost": 210.00,
"overrides": {
"db": {"plan_name": "tier-2", "storage_size_gb": 50}
}
}'
3. Poll for status
The stack provisions asynchronously. Poll GET /stacks/{stack-id} until status reaches Running:
curl https://api.foundrydb.com/stacks/$STACK_ID \
-H "Authorization: Bearer $FOUNDRYDB_TOKEN"
Typical progression is Pending → Provisioning → Wiring → Running. The Metabase app waits on the database: it only finishes once PostgreSQL is Running, then the engine wires the connection in. Most launches complete within a few minutes.
Once the stack is Running, the response carries the live workspace URL in endpoint_url:
{
"id": "stk_...",
"name": "my-bi-workspace",
"status": "Running",
"endpoint_url": "https://my-bi-workspace.foundrydb.com",
"resources": [
{ "symbolic_name": "db", "kind": "database", "status": "Running", "service_id": "..." },
{ "symbolic_name": "app", "kind": "app", "status": "Running", "service_id": "..." }
]
}
You can pull just the endpoint with:
curl -s https://api.foundrydb.com/stacks/$STACK_ID \
-H "Authorization: Bearer $FOUNDRYDB_TOKEN" \
| grep -o '"endpoint_url":"[^"]*"'
First run
1. Open Metabase
Open the endpoint_url in your browser. It is a real foundrydb.com hostname with a valid certificate, so there is no warning to click through.
2. Create the first admin
Metabase greets a fresh install with a setup wizard. Pick a language, then create the first admin account with your name, email, and a password. This account is the owner of the workspace; you can invite more users from Settings → Admin → People later.
The wizard may offer to connect a database. You can skip that step: the stack already registered your PostgreSQL as a data source during wiring. Choose "I'll add my data later" and finish the wizard.
3. Confirm your database is connected
Open Settings → Admin → Databases. You will see the stack's PostgreSQL listed and synced. Metabase scans its schema so it can suggest tables and columns when you build questions.
If you have not loaded any data yet, connect to the same PostgreSQL with your own client and create a table to explore. Retrieve the database credentials and host from the console under Databases, or via the API for the db resource's service_id. For example:
CREATE TABLE signups (
id serial PRIMARY KEY,
plan text NOT NULL,
region text NOT NULL,
amount numeric(10,2) NOT NULL,
at timestamptz NOT NULL DEFAULT now()
);
INSERT INTO signups (plan, region, amount) VALUES
('starter', 'eu-west', 29.00),
('pro', 'eu-north', 99.00),
('pro', 'eu-west', 99.00),
('starter', 'eu-north', 29.00),
('scale', 'eu-west', 299.00);
Back in Metabase, open Settings → Admin → Databases, select your database, and trigger Sync database schema now so the new table appears.
4. Ask a question
Click + New → Question, pick your database and the signups table, then summarize. For example, group by region and sum amount to see revenue per region. Metabase renders the result and lets you switch the visualization between a table, a bar chart, a line, and more. Save the question with a name.
Prefer SQL? Click + New → SQL query, select your database, and run a query directly:
SELECT plan, count(*) AS signups, sum(amount) AS revenue
FROM signups
GROUP BY plan
ORDER BY revenue DESC;
5. Build a dashboard
Click + New → Dashboard, give it a name, then add your saved questions to it. Drag the tiles to arrange them, resize them, and add a filter (for example, a date range on at) that applies across every card. You now have a live dashboard that refreshes against your data.
Everything you just created, the admin account, the questions, the dashboard, and the database registration, persists into your PostgreSQL. The Metabase application volume holds runtime state, but the workspace itself lives in the database you own.
How the wiring works
The stack engine does not introduce a new provisioning path. It provisions the two resources in dependency order and then injects the configuration each one needs.
- Provision in order. The dependency graph in the template says
appdepends ondb, so PostgreSQL is created first. Metabase is provisioned in parallel but does not finish wiring until the database isRunning. - Attach. The
appresource declaresattachment_kind: metabaseandattached_to: [$db]. During theWiringphase, the engine attaches the Metabase app to the database service. - Inject the connection. The attachment supplies Metabase with the PostgreSQL connection details so it uses that database as its application database and registers it as a browsable, queryable data source. There is no connection string for you to copy and no firewall rule to open by hand.
Because the attachment uses the same primitives you would use yourself, both resources are ordinary services in your account afterward. You can scale the database, inspect its metrics, take backups, and manage the Metabase app independently, all from the console.
Cost and EU residency
You see the exact monthly cost in the preview before anything is provisioned, and the accepted figure is re-checked at launch time. Both resources are billed through your normal plan, the same as if you had created them individually.
Both the database and the Metabase app are EU-resident. Residency is not a setting you remember to flip; it is where the platform runs. Your data, your dashboards, and your queries stay within the platform's European footprint.
Teardown
A stack is launched as one unit and torn down as one unit:
curl -X DELETE https://api.foundrydb.com/stacks/$STACK_ID \
-H "Authorization: Bearer $FOUNDRYDB_TOKEN"
This returns 202 Accepted. The reconciler deletes both child resources in reverse dependency order, leaving nothing orphaned. Teardown is irreversible, so export any dashboards or data you want to keep first.
Next steps
- Stacks Overview: the guarantees behind every stack, including cost transparency, atomic rollback, and EU residency.
- Launch a Stack: the full preview, launch, retry, and lifecycle reference.
- Upgrades: adopt a new template version in place when
bi-workspaceis bumped. - Authoring Templates: compose your own stack and publish it to the marketplace.