Docs/ Databases/ Connection Strings

Connection Strings

Connect your applications to databases with auto-injected environment variables. sh0 handles internal networking so your app can reach its database by hostname.

Finding Connection Strings

Every database created in sh0 has its connection details available in the dashboard. Navigate to the database detail page and click the Connection tab to see all connection information.

Database connection tab -- showing the full connection string, host, port, username, password, and database name

The connection tab displays:

  • Full connection URL -- Ready to copy and paste into your app configuration.
  • Individual fields -- Host, port, username, password, and database name as separate values.
  • Connection command -- A CLI command to connect directly (e.g., psql, mysql).

For example, a PostgreSQL database connection string looks like:

PostgreSQL Connection URL
postgresql://myuser:secretpass@mydb:5432/myapp

Auto-Injected Environment Variables

When you create a database in a stack, sh0 automatically injects connection environment variables into all application services within the same stack. Your app can read these variables at runtime without any manual configuration.

Environment variables panel -- showing auto-injected database variables with a badge indicating they are managed by sh0

Variable Naming Convention

Auto-injected variables follow a consistent naming pattern based on the database name and engine:

PostgreSQL (database named 'mydb')
DATABASE_URL=postgresql://sh0:generated_pass@mydb:5432/sh0
MYDB_HOST=mydb
MYDB_PORT=5432
MYDB_USER=sh0
MYDB_PASSWORD=generated_pass
MYDB_DATABASE=sh0
MySQL (database named 'maindb')
DATABASE_URL=mysql://sh0:generated_pass@maindb:3306/sh0
MAINDB_HOST=maindb
MAINDB_PORT=3306
MAINDB_USER=sh0
MAINDB_PASSWORD=generated_pass
MAINDB_DATABASE=sh0
Redis (database named 'cache')
REDIS_URL=redis://:generated_pass@cache:6379
CACHE_HOST=cache
CACHE_PORT=6379
CACHE_PASSWORD=generated_pass
MongoDB (database named 'docs')
MONGO_URL=mongodb://sh0:generated_pass@docs:27017/sh0
DOCS_HOST=docs
DOCS_PORT=27017
DOCS_USER=sh0
DOCS_PASSWORD=generated_pass
DOCS_DATABASE=sh0
Tip
If your stack has a single database, sh0 also sets DATABASE_URL (or REDIS_URL / MONGO_URL) as a convenience. If you have multiple databases of the same engine, use the name-prefixed variables to avoid conflicts.

Connecting from the Same Stack

Services within the same stack share a Docker network. This means your app can connect to the database using the database container's name as the hostname. No IP addresses, no port mapping -- just the container name.

Node.js example
// The DATABASE_URL is auto-injected by sh0
const pool = new Pool({
  connectionString: process.env.DATABASE_URL,
});
Python / Django example
# settings.py
import dj_database_url

DATABASES = {
    'default': dj_database_url.config(
        default=os.environ['DATABASE_URL']
    )
}
Stack network diagram -- showing an app container and database container connected on the same internal Docker network
Note
Internal connections between containers in the same stack do not leave the Docker network. Traffic is not encrypted via TLS because it never touches the public internet. This is standard Docker networking behavior.

External Access

By default, databases are only accessible from within the stack network. To connect from your local machine (for example, using a GUI tool like pgAdmin, TablePlus, or DBeaver), you need to enable external access.

  1. Open the database settings.
  2. Toggle Public Access to enable it.
  3. sh0 maps the container port to a random high port on the host (e.g., 54321).
  4. Connect using your-server-ip:54321 with your database credentials.
External access toggle and the resulting public connection string with the mapped port
Warning
Enabling external access exposes your database to the internet. Always use strong passwords and consider restricting access by IP address using firewall rules.

Connection Pooling

Most databases have a limit on the number of concurrent connections. Connection pooling helps you stay within these limits while serving many requests.

Best practices for connection pooling in sh0:

  • Use your framework's built-in pool -- Most ORMs and database drivers support connection pooling. Configure the pool size based on your database limits.
  • Match pool size to available connections -- PostgreSQL defaults to 100 max connections. If you have 3 app replicas, set each pool to ~30 connections.
  • Set connection timeouts -- Configure idle connection timeouts to prevent stale connections from consuming slots.
  • Monitor connection count -- Use the database metrics dashboard to track active connections over time.
Node.js pool configuration
const pool = new Pool({
  connectionString: process.env.DATABASE_URL,
  max: 20,              // Maximum connections in the pool
  idleTimeoutMillis: 30000,  // Close idle connections after 30s
  connectionTimeoutMillis: 5000, // Fail if connection takes > 5s
});

Common Framework Examples

Here are connection examples for popular frameworks. All of them use the DATABASE_URL environment variable that sh0 injects automatically.

Ruby on Rails (config/database.yml)
production:
  url: <%= ENV['DATABASE_URL'] %>
Laravel (.env)
DB_CONNECTION=pgsql
DB_HOST=${{ MYDB_HOST }}
DB_PORT=${{ MYDB_PORT }}
DB_DATABASE=${{ MYDB_DATABASE }}
DB_USERNAME=${{ MYDB_USER }}
DB_PASSWORD=${{ MYDB_PASSWORD }}
Rust / SQLx
let pool = PgPoolOptions::new()
    .max_connections(20)
    .connect(&std::env::var("DATABASE_URL")?)
    .await?;
Go / pgx
pool, err := pgxpool.New(ctx, os.Getenv("DATABASE_URL"))
Tip
Most modern frameworks auto-detect DATABASE_URL. If yours does, you do not need to configure anything -- just deploy to sh0 and it works out of the box.