# Connecting to your database

> Every way to reach a SupaHost project's Postgres database, per plan: the Data API, Studio's SQL editor, MCP execute_sql, and direct Postgres over an SSH tunnel on Business.

Source: https://supahost.app/docs/database/connecting · Updated 2026-11-11

There are four ways to reach a project's database on SupaHost. Which ones you can use depends on your plan and on whether you're the instance owner. There's no public Postgres port and no connection pooler, so the usual Supabase Cloud connection strings (`db.<ref>.supabase.co`, port 6543) don't apply here.

| Option | Plans | Who | Speaks |
|---|---|---|---|
| Data API (REST) | All | Anyone with the project URL and a key | HTTPS |
| Studio SQL editor | All | Owner | Browser |
| MCP `execute_sql` | All | Anyone holding an access token | HTTPS (MCP) |
| Direct Postgres over SSH tunnel | Business, Enterprise | Owner (or someone the owner gives the string to) | Postgres wire protocol |

If you only need a copy of the data, any plan can also download a `pg_dump` file from the Backups tab. See [Exporting your data](/docs/platform/exports).

## Data API: from your app

This is how your application should talk to the database on every plan. PostgREST turns your tables, views and functions into a REST API, and supabase-js wraps it.

Find the values in *Dashboard → your project → **Connect** tab → **App***: the Project URL, the `anon` key (labelled "public") and the `service_role` key (labelled "secret", behind **Reveal**, owner only).

```bash
# .env
SUPABASE_URL=https://app-one.acme.supahost.space
SUPABASE_ANON_KEY=eyJhbGciOi...
```

```ts
import { createClient } from '@supabase/supabase-js'

const supabase = createClient(process.env.SUPABASE_URL!, process.env.SUPABASE_ANON_KEY!)

const { data, error } = await supabase
  .from('bookings')
  .select('id, starts_at, room')
  .gte('starts_at', new Date().toISOString())
  .order('starts_at')
```

The Data API works from browsers, mobile apps, serverless functions and edge runtimes alike, because it's plain HTTPS. Access is controlled by grants and [Row Level Security](/docs/database/row-level-security). See [The Data API](/docs/api/overview).

## Studio SQL editor: ad-hoc SQL in the browser

The instance owner can open Supabase Studio for any project and run SQL there. Go to *Dashboard → your project → **Database** tab → **Open Studio*** (or use the Studio button in the project header), then pick the SQL editor.

Studio connects as the `postgres` role, so the SQL editor can create tables, write policies and enable extensions. Studio takes about 20 seconds to start on first visit. See [Using Supabase Studio](/docs/database/studio).

## MCP execute_sql: for AI coding agents

The SupaHost MCP server lets tools such as Claude Code or Cursor run SQL against a project with the `execute_sql` tool, and change the schema with `apply_migration`.

1. Create a token in *Dashboard → **AI agents (MCP)*** (or *your project → **Connect** → **AI agents (MCP)***). Choose the scope (one project or the whole instance) and tick **Read-only** if the agent should only look.
2. Add the server to your client using the snippet shown. The endpoint is `https://mcp.supahost.space/mcp`, with the token sent as `Authorization: Bearer shp_...`.

In read-only mode, SQL runs as a role that can read everything but can't write, and the write tools aren't offered at all. See [The SupaHost MCP server](/docs/ai-tools/mcp).

## Direct Postgres: Business and Enterprise

On Business and Enterprise you can connect psql, pg_dump, Prisma, Drizzle, DBeaver or any other Postgres client from your own machine. Postgres itself only listens on `127.0.0.1` inside the VM, so you reach it through an SSH tunnel.

**1. Add your SSH public key.** Go to *your project → **Connect** → **SSH & CLI***, paste the key into **Public key** and click **Add key**. It becomes active within a minute. Supported types are ed25519, RSA (2048 bits or more), ECDSA and the security-key variants. An instance can hold up to 20 keys.

**2. Open the tunnel** and leave it running. With instance `acme`:

```bash
ssh -N -L 5432:127.0.0.1:5432 supahost@acme.supahost.space
```

**3. Get the connection string.** In *your project → **Connect** → **Database***, click **Show connection string** (owner only). It looks like this and only works while the tunnel is open:

```
postgresql://postgres:<password>@127.0.0.1:5432/p_app_one
```

The database name is `p_` plus the project name with hyphens turned into underscores.

**4. Connect.**

```bash
psql "postgresql://postgres:<password>@127.0.0.1:5432/p_app_one"
```

If something on your machine already uses port 5432 (a local Postgres, or the Supabase CLI's database), forward a different local port and use it in the string:

```bash
ssh -N -L 5433:127.0.0.1:5432 supahost@acme.supahost.space
psql "postgresql://postgres:<password>@127.0.0.1:5433/p_app_one"
```

### psql on the VM itself

The same SSH key also lets you run a few commands on the instance without a tunnel:

```bash
ssh supahost@acme.supahost.space
sudo supahost-psql app-one                      # interactive psql as postgres
sudo supahost-psql app-one -c "select count(*) from bookings"
sudo supahost-db-url app-one                    # prints the tunnel connection string
```

The `supahost` user has no root and can only run these commands (plus `supahost-logs` and `supahost-status`). See [SSH access and direct Postgres](/docs/platform/ssh).

## Connections are a shared budget

Postgres on your instance allows 400 connections in total, shared by every project and by the platform's own services. There's no pooler in front of it. When you connect an ORM or a worker over the tunnel, set a small pool size (a handful per process is plenty) and close idle connections. See [Connections and timeouts](/docs/database/connections-and-timeouts).

## Serverless and edge code

Serverless functions and edge runtimes open many short-lived connections, which is the case a pooler exists for. On SupaHost, call the Data API from that code with supabase-js instead, or move the logic into a [database function](/docs/database/functions) and call it with RPC. Edge Functions on SupaHost get `SUPABASE_URL` and the keys as environment variables, but no database URL.

## Troubleshooting

- [Connecting directly to Postgres (psql, pg_dump, ORMs)](/kb/direct-postgres-connection)
- [Connection refused or timeout when connecting to Postgres](/kb/connection-refused)
- [FATAL: password authentication failed](/kb/password-authentication-failed)
- [Too many connections](/kb/too-many-connections)
