Internal networking
Everything you deploy in one organization lands in the same private network. Your backend can reach your database, your KV store, and your other services directly by hostname — the traffic never leaves the cluster, never crosses the public internet, and never needs a public endpoint at all.
This page shows how to wire that up.
The shape of it
Section titled “The shape of it”Each organization gets its own isolated namespace. Inside it, every service has a stable internal DNS name:
| Resource | Internal hostname | Port |
|---|---|---|
| Container app | custom-<project-name> | 80 |
| PostgreSQL | <db-name>-postgresql.org-<orgId>.svc.<region>.pandastack.app | 5432 |
| MySQL | <db-name>-mysql.org-<orgId>.svc.<region>.pandastack.app | 3306 |
| KV store (Redis) | <store-name>-redis.org-<orgId>.svc.<region>.pandastack.app | 6379 |
Two things follow from this that matter:
Traffic between them stays inside the network. A backend talking to its database over the internal hostname does plain TCP inside the cluster. There is no TLS handshake to pay for, no public proxy hop, and nothing observable from the outside.
Another organization cannot resolve or reach your services. The namespace is the isolation boundary — your services are addressable from your workloads, not from anyone else’s.
You usually don’t type any of this
Section titled “You usually don’t type any of this”The internal URLs are injected for you. Link a database or KV store to a project and PandaStack writes the connection string into that project’s environment and redeploys it:
| You link | Your app gets |
|---|---|
| A database | DATABASE_URL |
| A KV store | KV_URL |
Both point at the internal hostname, with real credentials already filled in. So the code you actually write is:
import { Pool } from "pg";import { createClient } from "redis";
const db = new Pool({ connectionString: process.env.DATABASE_URL });const kv = createClient({ url: process.env.KV_URL });No connection string to copy out of the dashboard, no secret to paste into a config file, nothing to rotate by hand. Unlink and the variable is removed and the app redeploys again.
Backend calling backend
Section titled “Backend calling backend”Container apps in the same organization reach each other by Helm release name, on port 80:
http://custom-<project-name>So if you deployed a project called api, another app in the same organization calls it at http://custom-api. This is the pattern for a frontend calling a backend, or a worker calling an internal service, without either one going out to the public internet and back.
Set it as an environment variable on the calling app so you’re not hardcoding it:
INTERNAL_API_URL=http://custom-apiKeeping a database or KV store off the public internet
Section titled “Keeping a database or KV store off the public internet”Both databases and KV stores are created as either public or private:
- Public — a TLS endpoint is issued at
<name>.db.pandastack.app, reachable from anywhere with the password. Use this when something outside PandaStack needs to connect: a local dev machine, a GUI client, an external service. - Private — no public endpoint is issued. There is no public hostname to hand out and none appears in the dashboard. Your apps still reach it on the internal hostname exactly as before.
If your app runs on PandaStack and nothing outside needs access, choose private. It’s the smaller surface, and you lose nothing — the internal path is the one your app was going to use anyway.
Choosing at creation
Section titled “Choosing at creation”Visibility is set when you create the resource:
curl -X POST https://api.pandastack.io/v1/kv \ -H "Authorization: Bearer $PANDASTACK_TOKEN" \ -H "Content-Type: application/json" \ -d '{"name":"sessions","tier":"kv-free","visibility":"private"}'In the dashboard, it’s the public/private choice in the create form for both databases and KV stores.
A worked example
Section titled “A worked example”A typical setup — a Next.js frontend, a Node API, Postgres, and Redis — wires up like this:
- Deploy the API as a project named
api. Link the database and the KV store to it. It now hasDATABASE_URLandKV_URLpointing at internal hostnames. - Create the database and KV store as private. Nothing outside PandaStack needs them.
- Deploy the frontend. Give it
INTERNAL_API_URL=http://custom-apifor server-side calls. - Only the frontend has a public URL. The API, the database, and the KV store are reachable from your own services and have no public address.
Server-side requests in the frontend hit http://custom-api and never leave the network. Browser-side requests still need a public route, so if the browser calls the API directly, the API needs its own public URL — internal DNS doesn’t resolve from a user’s laptop.
Related
Section titled “Related”- Connecting to a KV store — public-URL connection details and the redis-cli caveat
- Connecting to a database — public-URL connection details per engine
- Environment variables & secrets — how injected variables interact with your own