# FAQ (/docs/faq)
## How should I handle database connections on an app deployed to Phemeral? [#how-should-i-handle-database-connections-on-an-app-deployed-to-phemeral]
Database connections should not be expected to persist across invocations. Phemeral environments may recycle the underlying process between requests, which means idle connections in a pool can become stale or closed.
### Use your provider's connection pooler if available [#use-your-providers-connection-pooler-if-available]
If your database provider already offers a connection pooler, you don't need to manage connection pooling in your application. For example, Phemeral's managed Postgres offering provides a **pooled connection URI** by default, so your app code can connect directly without configuring its own pool. A **direct connection URI** is also available when you need to bypass the pooler.
Check your provider's documentation to see if a managed pooler is available. If it is, prefer that over application-level pooling.
### Application-level pooling [#application-level-pooling]
If you do manage your own connection pool, configure it to validate or recycle connections proactively.
### SQLAlchemy [#sqlalchemy]
Set `pool_pre_ping` to validate and re-establish connections before executing a query:
```python
from sqlalchemy import create_engine
engine = create_engine(
"postgresql+psycopg2://user:pass@host/db",
pool_pre_ping=True,
)
```
This issues a lightweight check (e.g. `SELECT 1`) on each connection checkout, automatically replacing connections that the server has closed.
### asyncpg [#asyncpg]
Set `max_inactive_connection_lifetime` to a low value (such as `1` second) so that idle connections in the pool are recycled frequently:
```python
import asyncpg;
pool = await asyncpg.create_pool(
"postgresql://user:pass@host/db",
max_inactive_connection_lifetime=1,
)
```
This ensures connections are not held long enough to go stale across invocations.
# Quickstart (/docs)
Phemeral deploys your Python backends automatically. Connect a GitHub repository, push your code, and get a live URL.
If you don't already have a project, use our [hello-world repository](https://github.com/phemeral-dev/hello-world) to get started!
## 1. Create an Account [#1-create-an-account]
Sign up at [phemeral.dev](https://phemeral.dev/pricing). When your account is created, Phemeral automatically provisions an organization with a default project called **Launchpad** and three default environments: **Production**, **Staging**, and **Development**.
## 2. Connect Your GitHub Account [#2-connect-your-github-account]
1. Navigate to [User Settings](/dashboard/user-settings).
2. Click **Connect** in the GitHub section.
3. Authorize the Phemeral GitHub App on your GitHub account and grant it access to the repositories you want to deploy.
## 3. Connect a Repository to Your Project [#3-connect-a-repository-to-your-project]
1. Open your project and go to the **Settings** tab.
2. Select the repository you want to deploy from the list of accessible repositories.
3. Map a branch (e.g. `main`) to an environment (e.g. **Production**).
## 4. Deploy [#4-deploy]
Push a commit to your mapped branch. Phemeral automatically:
* Detects your Python framework, package manager, and project structure
* Builds and deploys your application
* Assigns a live URL on `.phemeral.app`
View the build status and logs from the deployment page in your dashboard.
## Next Steps [#next-steps]
* [Connect GitHub](/docs/getting-started/connect-github): Detailed walkthrough of the GitHub setup
* [Your First Deployment](/docs/getting-started/first-deployment): Step-by-step tutorial for deploying a project
* [Concepts](/docs/concepts): Learn how Projects, Environments, and Deployments work together
# Database Clusters (/docs/concepts/database-clusters)
A **database cluster** is a fully managed Postgres database that belongs to one of your projects. Phemeral provisions the database, keeps it patched, and scales its compute up and down with your traffic.
Managed Postgres is available on the **Pro** plan.
## What a Database Cluster Contains [#what-a-database-cluster-contains]
Each cluster is an independent Postgres database with:
* A **database** and a **role** that owns it.
* A **pooled connection URI** your application uses to connect (recommended for most uses), plus a **direct connection URI** available when you need it.
* Its own compute, which scales independently of every other cluster.
## Clusters and Projects [#clusters-and-projects]
Database clusters are created inside a project, alongside that project's environments and deployments. A project can hold **up to 20 database clusters**.
Because clusters are associated to a project, they are deployed geographically close to that project's compute, reducing latency between your application and its database.
## Automatic Scaling [#automatic-scaling]
Clusters scale their compute automatically as load changes.
* Compute scales between **0.25 and 8 vCPU**, with **1 GB to 32 GB of RAM**, rising and falling with your traffic.
* When a cluster receives **no traffic for 5 minutes**, it **scales to zero**. While a cluster is scaled to zero, it incurs **no compute charge**.
* A cluster that has scaled to zero **scales back up within a few hundred milliseconds** the next time it is accessed, so the first query after an idle period transparently wakes it.
## Connection Pooling [#connection-pooling]
Every cluster is fronted by **a connection pooler**.
A single cluster supports up to **10,000 concurrent connections** through the pooler. The pooled connection URI is the default and is what you should use for most applications. A **direct connection URI** is also available for cases where you need to bypass the pooler, such as administrative tools or long-running sessions.
See the [FAQ](/docs/faq) for guidance on configuring your application's database client for an environment where processes may be recycled between requests.
## Extensions [#extensions]
Support for Postgres extensions is **coming soon**. Today, clusters run a standard Postgres 18 configuration.
## More [#more]
For step-by-step instructions, see [Create and Connect to a Database Cluster](/docs/guides/managed-postgres).
For more, see the [Managed Postgres reference](/docs/reference/managed-postgres).
# Deployments (/docs/concepts/deployments)
A **deployment** is a specific version of your code running inside an environment. Each time you push to a mapped branch or trigger a deploy, Phemeral creates a new deployment.
## Deployment Lifecycle [#deployment-lifecycle]
Every deployment moves through a series of stages:
1. **Building:** Phemeral analyzes your project, installs dependencies, and builds the project.
2. **Successful:** The build completed and the deployment is ready to serve traffic.
3. **Failed:** The build encountered an error. Check the build logs for details.
A deployment's status is one of: `building`, `successful`, or `failed`.
## What Happens During a Deployment [#what-happens-during-a-deployment]
When a deployment is created, Phemeral:
1. **Detects your project settings:** Python version, framework (FastAPI, Flask, or Django), package manager (uv, poetry, or pip), project root directory, and application entry point. See [Project Structure Requirements](/docs/reference/project-structure).
2. **Chooses a runtime command:** Phemeral uses the project's custom start command if one is saved. Otherwise, it uses the autodetected default command for the framework.
3. **Builds your project and assigns compute**
4. **Assigns a domain:** Every deployment receives an auto-generated URL in the format `{deployment-id}.phemeral.app`.
## Runtime Command Resolution [#runtime-command-resolution]
Phemeral still autodetects your framework, project root, and application entry point even when you use a custom start command.
That autodetection determines the default runtime behavior. A project-level custom start command only changes the command Phemeral starts for **new** deployments.
If you clear the custom command later, future deployments fall back to the autodetected default. Existing deployments are not modified.
## Build Logs [#build-logs]
Each stage of the build is logged with a timestamp. You can view build logs on the deployment detail page in the dashboard.
## Domains [#domains]
Deployments have two types of domains:
* **Deployment domain:** Auto-generated for every deployment: `{deployment-id}.phemeral.app`. This always points to the specific deployment, regardless of which deployment is current on the environment.
* **Environment domains:** Custom subdomains assigned to the environment (e.g. `my-api-production.phemeral.app`). These point to whichever deployment is currently active on the environment.
When a new deployment is set as the current deployment on its environment, the environment's custom domains begin routing traffic to the new deployment.
## Runtime [#runtime]
Deployments run on optimized compute managed by Phemeral's compute orchestration layer.
Compute resources scale to zero when traffic is idle, and scale up (almost) instantly when requests arrive (\<75ms).
## Setting the Current Deployment [#setting-the-current-deployment]
When a deployment triggered by a GitHub push completes successfully, it is automatically set as the current deployment on its environment. The environment's custom domains immediately begin routing traffic to the new deployment.
## Runtime Logs [#runtime-logs]
In addition to build logs, you can view runtime logs for a deployment. These are the logs your application produces while handling requests. Runtime logs are available on the deployment detail page and support pagination.
# Environments (/docs/concepts/environments)
An **environment** is a deployment target within a project. Environments let you run different versions of your code side by side, such as a production environment serving live traffic and a staging environment for testing.
## What an Environment Contains [#what-an-environment-contains]
Each environment has:
* **A current deployment:** The deployment that currently receives live traffic for this environment. When a new deployment succeeds, it can be set as the current deployment.
* **Deployment history:** A record of all deployments created for this environment.
* **Environment variables:** Key-value pairs that are injected into your application at build time. Values are encrypted at rest. See [Manage Environment Variables](/docs/guides/environment-variables).
* **Custom domains:** One or more subdomains on `.phemeral.app` that route traffic to the environment's current deployment. See [Configure Custom Domains](/docs/guides/custom-domains).
* **GitHub branch mapping:** An optional link between a GitHub branch and this environment. Pushes to the mapped branch trigger automatic deployments. See [Set Up GitHub Continuous Deployment](/docs/guides/github-integration).
* **Scheduled webhooks:** Optional scheduled HTTP requests that target the environment's current deployment through its active domain. See [Configure Scheduled Webhooks](/docs/guides/scheduled-webhooks).
## Creating an Environment [#creating-an-environment]
When you create a project, Phemeral automatically creates three environments for you: **Production**, **Staging**, and **Development**. You can create additional environments from the project's **Environments** page.
When creating an environment, you provide:
* An **environment name**.
* Optionally, **initial environment variables**.
Project creation provides separate variable groups for **Production**, **Staging**, and **Development**.
## How Traffic Reaches an Environment [#how-traffic-reaches-an-environment]
Each environment can be assigned one or more **custom domains** in the format `{subdomain}.phemeral.app`. When a request arrives at a custom domain, it is routed to the environment's **current deployment**.
Individual deployments also have their own auto-generated domains in the format `{deployment-id}.phemeral.app`. These are useful for previewing a specific deployment regardless of which deployment is currently active on the environment.
## Environments and Branches [#environments-and-branches]
An environment can have a GitHub branch mapped to it. When code is pushed to that branch, Phemeral automatically:
1. Downloads the code from the repository.
2. Creates a new deployment in the mapped environment.
3. Sets the new deployment as the environment's current deployment.
Multiple environments can map to different branches of the same repository. For example:
| Environment | Branch |
| ----------- | ---------------------- |
| Production | `main` |
| Staging | `pre-release` |
| Development | `fancy-feature-branch` |
Unmapping a branch stops automatic deployments for that environment. Existing deployments are not affected.
## Scheduled Webhooks [#scheduled-webhooks]
Scheduled webhooks are environment-bound HTTP requests that Phemeral runs on a UTC cron schedule.
Although you configure them from the project's **Settings** tab, each scheduled webhook targets one environment. Phemeral sends the request to that environment's oldest active domain, which means the request always reaches the environment's **current deployment**.
This makes scheduled webhooks useful for tasks that should follow an environment over time, such as:
* warming caches after traffic goes idle
* calling internal maintenance endpoints
* triggering application-level jobs on a schedule
If an environment has no active domains, scheduled webhooks for that environment cannot run until a domain becomes active again.
# Platform Overview (/docs/concepts)
Phemeral is a deployment platform for Python backends. It takes your source code, automatically detects your framework and dependencies, builds your application, and runs it on a lightweight virtual machine with a public URL.
## How Phemeral Works [#how-phemeral-works]
When you push code to a connected GitHub repository, Phemeral:
1. Downloads the source code from your repository.
2. Analyzes the project to detect the Python framework (FastAPI, Flask, or Django), package manager (uv, poetry, or pip), and application entry point.
3. Builds your project
4. Deploys the built project to the Phemeral cloud
5. Assigns a public URL on `.phemeral.app` and serves traffic to your application.
## Core Concepts [#core-concepts]
Phemeral is organized around three main concepts:
* **[Projects](/docs/concepts/projects):** A project groups related environments together, connects to a single GitHub repository, and can define a project-level start command for new deployments.
* **[Environments](/docs/concepts/environments):** An environment is a deployment target within a project (e.g. production, staging). Each environment has its own configuration, environment variables, and custom domains.
* **[Deployments](/docs/concepts/deployments):** A deployment is a specific version of your code running in an environment. Environments track a current deployment that receives live traffic.
### How They Relate [#how-they-relate]
```
Organization
└── Project (connected to a GitHub repository)
├── Environment: "Production" (branch: main)
│ ├── Current Deployment → receives traffic
│ └── Previous Deployments (history)
├── Environment: "Staging" (branch: pre-release)
│ ├── Current Deployment → receives traffic
│ └── Previous Deployments (history)
└── Environment: "Development" (branch: fancy-feature-branch)
├── Current Deployment → receives traffic
└── Previous Deployments (history)
```
An **organization** is the top-level container. It holds your team members, billing plan, and projects. When you create an account, an organization is created for you with a default project called **Launchpad** and three default environments: **Production**, **Staging**, and **Development**.
## Supported Stack [#supported-stack]
Phemeral currently supports Python backends using:
| Category | Supported Options |
| ---------------- | ------------------------------------------------------------------------------- |
| Frameworks | FastAPI, Flask, Django |
| Package managers | uv, poetry, pip (requirements.txt), or any pyproject.toml based package manager |
| Python versions | Specified via `.python-version` file (defaults to 3.12 if unspecified) |
See [Supported Frameworks](/docs/reference/supported-frameworks) for details on how autodetection works.
# Projects (/docs/concepts/projects)
A **project** is a container that groups related environments together. Each project can be connected to a single GitHub repository for continuous deployment.
## What a Project Contains [#what-a-project-contains]
A project holds:
* **Environments:** One or more deployment targets (e.g. production, staging, preview). See [Environments](/docs/concepts/environments).
* **GitHub repository connection:** An optional link to a GitHub repository. When connected, pushes to mapped branches trigger automatic deployments.
* **Deployment startup configuration:** An optional custom start command that overrides Phemeral's autodetected runtime command for new deployments in the project.
* **Deployment history:** All deployments created across the project's environments.
## Creating a Project [#creating-a-project]
When you create a new project, you provide:
* A **project name**.
* Optionally, **initial environment variables** for the **Production**, **Staging**, and **Development** environments.
Every new project starts with three environments: **Production**, **Staging**, and **Development**.
Every organization starts with a default project called **Launchpad** that includes those same three environments.
You can create additional projects from the dashboard by navigating to **Dashboard → New Project**.
## Connecting a GitHub Repository [#connecting-a-github-repository]
A project can be connected to one GitHub repository at a time. This enables continuous deployment: when you push to a branch that is mapped to an environment, Phemeral automatically creates a new deployment.
To connect a repository:
1. Ensure your GitHub account is connected in [User Settings](/dashboard/user-settings).
2. Open your project's **Settings** tab.
3. Select a repository from the list of repositories that the Phemeral GitHub App can access.
When you disconnect a repository, all branch-to-environment mappings for the project are removed. Existing deployments are not affected.
See [Set Up GitHub Continuous Deployment](/docs/guides/github-integration) for the full setup guide.
## Project-Level Start Command [#project-level-start-command]
Projects can optionally define a custom start command from the **Settings** tab.
When a custom command is saved, new deployments for that project use it instead of Phemeral's autodetected `uvicorn` or `gunicorn` command. Clearing the saved value returns the project to autodetection.
This setting is shared across the project. It does not change existing deployments that have already been created.
See [Set a Custom Start Command](/docs/guides/custom-start-command) for the workflow and [Supported Frameworks](/docs/reference/supported-frameworks) for the autodetected defaults.
## Projects and Organizations [#projects-and-organizations]
Each project belongs to a single organization. All members of the organization can access its projects. There is no per-project access control; access is managed at the organization level.
# Connect Your GitHub Account (/docs/getting-started/connect-github)
Before Phemeral can deploy code from your GitHub repositories, you need to connect your GitHub account and authorize the Phemeral GitHub App.
## Step 1: Open User Settings [#step-1-open-user-settings]
Navigate to [User Settings](/dashboard/user-settings) in the Phemeral dashboard.
## Step 2: Connect GitHub [#step-2-connect-github]
In the **GitHub** section, click **Connect**. This redirects you to GitHub to authorize the Phemeral OAuth integration.
Sign in to GitHub (if not already signed in) and authorize the application. After authorizing, you will be prompted to install the **Phemeral GitHub App** on your GitHub account or organization.
During installation, GitHub will ask you to choose which repositories the app can access. You can grant access to all repositories or select specific ones.
## Step 3: Verify the Connection [#step-3-verify-the-connection]
After completing the GitHub authorization and app installation, return to [User Settings](/dashboard/user-settings). The GitHub section should show your account as connected.
## What Happens Next [#what-happens-next]
With your GitHub account connected, you can now:
* Connect a repository to a Phemeral project (from the project's **Settings** tab).
* Map branches to environments for automatic deployments.
Continue to [Deploy Your First Project](/docs/getting-started/first-deployment) for a step-by-step walkthrough.
## Disconnecting GitHub [#disconnecting-github]
To disconnect your GitHub account, visit [User Settings](/dashboard/user-settings) and click **Disconnect** in the GitHub section. This revokes the connection. Any existing repository connections on your projects remain in place but will stop receiving new push events until a GitHub account is reconnected.
# Deploy Your First Project (/docs/getting-started/first-deployment)
This tutorial walks you through deploying a Python backend on Phemeral end-to-end. You will create a project, connect a GitHub repository, map a branch, and push a commit to trigger your first deployment.
## Prerequisites [#prerequisites]
* A Phemeral account with a [connected GitHub account](/docs/getting-started/connect-github).
* A GitHub repository containing a Python backend using FastAPI, Flask, or Django. See [Supported Frameworks](/docs/reference/supported-frameworks) for details.
## Step 1: Create a Project [#step-1-create-a-project]
When you first sign up, Phemeral creates a default **Launchpad** project with **Production**, **Staging**, and **Development** environments. You can use this project or create a new one:
1. From the dashboard, click **New Project**.
2. Enter a **project name**.
3. On the **Environment Variables** step, optionally add any variables your application needs (e.g. `DATABASE_URL`, `SECRET_KEY`). **Production** is selected by default; switch the environment selector to add separate variables for **Staging** or **Development**. You can enter variables individually or import a `.env` file or pasted snippet. See [Manage Environment Variables](/docs/guides/environment-variables).
4. Click **Create Project**.
You are redirected to the project page.
## Step 2: Connect a GitHub Repository [#step-2-connect-a-github-repository]
1. On your project page, go to the **Settings** tab.
2. In the **GitHub Repository** section, select the repository you want to deploy from the dropdown. This list shows repositories that Phemeral has access to.
3. Confirm the connection.
The project is now linked to your repository.
If your app later needs a different runtime command than the one Phemeral detects automatically, you can override it from the project's **Settings** tab. See [Set a Custom Start Command](/docs/guides/custom-start-command).
## Step 3: Map a Branch to an Environment [#step-3-map-a-branch-to-an-environment]
Still on the **Settings** tab:
1. Find the **Branch Mappings** section.
2. Select a branch from your repository (e.g. `main`).
3. Select the environment to deploy to (e.g. **Development**).
4. Save the mapping.
From now on, every push to the mapped branch triggers an automatic deployment to that environment.
## Step 4: Push Code and Deploy [#step-4-push-code-and-deploy]
Push a commit to the branch you mapped (e.g. `main`):
```bash
git add .
git commit -m "Initial deployment"
git push origin main
```
Phemeral receives the push event via the GitHub webhook and starts a deployment.
## Step 5: Monitor the Deployment [#step-5-monitor-the-deployment]
1. Navigate to your project in the dashboard.
2. Open the **Deployments** tab or click the latest deployment.
3. Watch the build progress and view logs.
When the status changes to **Successful**, your deployment is live.
## Step 6: Visit Your Deployment [#step-6-visit-your-deployment]
Every successful deployment receives a URL in the format:
```
{deployment-id}.phemeral.app
```
Click the deployment URL in the dashboard to visit your running application.
If you assigned a custom domain to the environment, that domain also points to the new deployment. See [Configure Custom Domains](/docs/guides/custom-domains).
## Next Steps [#next-steps]
* [Set Up GitHub Continuous Deployment](/docs/guides/github-integration): Map multiple branches to different environments.
* [Manage Environment Variables](/docs/guides/environment-variables): Add secrets and configuration to your environments.
* [Configure Custom Domains](/docs/guides/custom-domains): Give your environment a memorable subdomain.
# Getting Started (/docs/getting-started)
This section walks you through setting up Phemeral from scratch. By the end, you will have a Python backend deployed and accessible at a public URL.
## Prerequisites [#prerequisites]
* A GitHub account with at least one repository containing a Python backend (FastAPI, Flask, or Django).
* A Phemeral account. Sign up at [phemeral.dev](https://phemeral.dev).
## Steps [#steps]
1. **[Connect Your GitHub Account](/docs/getting-started/connect-github):** Authorize the Phemeral GitHub App so that Phemeral can access your repositories.
2. **[Deploy Your First Project](/docs/getting-started/first-deployment):** Connect a repository, map a branch, and push code to trigger your first deployment.
# Configure Custom Domains (/docs/guides/custom-domains)
Environment domains give your environment a memorable, stable URL that persists across deployments. Instead of using a deployment-specific URL that changes with each deploy, an environment domain always points to the environment's current deployment.
Phemeral supports two kinds of environment domains:
1. **Custom domains:** Hostnames you own, such as `api.example.com`.
2. **Phemeral subdomains:** Vanity subdomains of `.phemeral.app`, such as `my-api.phemeral.app`.
Both are assigned to an **environment**, not a specific deployment. Traffic is routed to whichever deployment is currently active on that environment, and when a new deployment is set as current, the domain automatically begins routing to it.
## Custom Domains [#custom-domains]
Use a custom domain when you want your environment to be reachable via a hostname you already own (for example, `api.example.com` or `app.example.com`).
### How custom domains work [#how-custom-domains-work]
* You can add any fully-qualified hostname you control, as long as it is not already in use by another Phemeral environment.
* The domain is created in a **Pending DNS** state. Phemeral checks whether the hostname's DNS records point at the platform.
* Once the DNS records are detected, the domain becomes **Active** and traffic is routed to the environment's current deployment.
* If the DNS check fails, the domain remains in a pending state
### DNS requirements [#dns-requirements]
Before adding a custom domain, configure your DNS provider to point the hostname at Phemeral using one or both of the following record types:
| Record type | Target |
| ----------- | ---------------------------------- |
| **A** | Provided IPv4 addresses |
| **AAAA** | Provided IPv6 addresses (optional) |
The exact IP addresses are shown in the dashboard when you add a custom domain.
### Add a custom domain [#add-a-custom-domain]
1. Navigate to your project in the dashboard.
2. Open the environment you want to assign the domain to.
3. In the **Domains** section, click **Add Domain**.
4. Enter the full hostname (for example, `api.example.com`).
If its DNS records are already pointing at Phemeral, it becomes **Active** right away. Otherwise it enters the **Pending DNS** state.
### Verify a custom domain [#verify-a-custom-domain]
If a custom domain is pending, you can trigger a DNS recheck at any time:
1. In the **Domains** section, find the pending custom domain.
2. Click **Verify DNS**.
If the DNS records are correct, the domain becomes **Active**. If not, fix the configuration and try again.
### Remove a custom domain [#remove-a-custom-domain]
1. Open the environment in the dashboard.
2. In the **Domains** section, find the custom domain you want to remove.
3. Click **Remove Domain**.
Traffic to the removed domain will no longer be routed to your environment.
## Phemeral Subdomains [#phemeral-subdomains]
Use a Phemeral subdomain when you want a clean, memorable URL under `.phemeral.app` without managing external DNS.
### How Phemeral subdomains work [#how-phemeral-subdomains-work]
* Every environment automatically receives a default subdomain in the format `{project-name}-{environment-name}.phemeral.app` when it is created.
* You can add additional vanity subdomains (for example, `api.phemeral.app` or `my-app.phemeral.app`) as long as they are not already taken.
* Phemeral subdomains are **Active** immediately; no DNS setup is required.
### Add a Phemeral subdomain [#add-a-phemeral-subdomain]
1. Navigate to your project in the dashboard.
2. Open the environment you want to assign a subdomain to.
3. In the **Domains** section, click **Add Domain**.
4. Enter the subdomain you want, including the `.phemeral.app` suffix (for example, `my-app.phemeral.app`).
If the subdomain is available, it is assigned to your environment immediately. Otherwise, choose a different subdomain and try again.
### Remove a Phemeral subdomain [#remove-a-phemeral-subdomain]
1. Open the environment in the dashboard.
2. In the **Domains** section, find the subdomain you want to remove.
3. Click **Remove Domain**.
Traffic to the removed subdomain will no longer be routed to your environment.
## Multiple Domains [#multiple-domains]
An environment can have any mix of custom domains and Phemeral subdomains. All of them route to the same current deployment.
## Deployment Domains vs. Environment Domains [#deployment-domains-vs-environment-domains]
| Type | Format | Points to |
| ------------------ | ------------------------------------ | ------------------------------------ |
| Deployment domain | `{deployment-id}.phemeral.app` | A specific deployment (always) |
| Environment domain | Any active custom or platform domain | The environment's current deployment |
Deployment domains are auto-generated and immutable. They are useful for previewing or testing a specific deployment. Environment domains follow the current deployment as it changes.
# Set a Custom Root Directory (/docs/guides/custom-root-directory)
Use this guide when your application lives in a subdirectory and Phemeral's default project root detection is not the directory you want to deploy.
## Before You Begin [#before-you-begin]
* A Phemeral project connected to a repository.
* Access to the project's **Settings** tab.
* The repository path to the Python service you want Phemeral to build and run.
Phemeral saves the custom root directory at the **project** level. New deployments for that project use the saved directory until you clear it.
## When to Use a Custom Root Directory [#when-to-use-a-custom-root-directory]
Most projects should keep autodetection enabled. Set a custom root directory only when Phemeral should look in a specific subdirectory for dependency files and your app entry point.
Common cases include:
* A monorepo where your Python backend lives under a folder such as `backend/` or `services/api/`.
* A repository that contains multiple deployable services.
* A repository where the shallowest dependency file belongs to a different tool or service than the one you want to deploy.
## Save a Custom Root Directory [#save-a-custom-root-directory]
1. Open your project in the dashboard.
2. Go to the **Settings** tab.
3. Find the **Root Directory** section.
4. Enter the path to your app directory, relative to the repository root.
5. Click **Save Root Directory**.
After the directory is saved, the section shows the project as using **Custom** root detection.
## Path Requirements [#path-requirements]
The saved path must:
* Be relative to the repository root.
* Point to a directory in the repository.
* Stay inside the repository.
The path must not:
* Start with `/`.
* Use `..` to move outside the repository.
Examples:
```text
backend
services/api
apps/customer-service
```
## What Changes After You Save It [#what-changes-after-you-save-it]
For future deployments, Phemeral starts dependency and app discovery inside the saved directory instead of searching from the repository root.
Within that directory, Phemeral still uses the normal detection rules:
* Dependency files are checked in this order: `uv.lock`, `poetry.lock`, `pyproject.toml`, then `requirements.txt`.
* The shallowest matching dependency file inside the selected directory wins.
* App discovery runs from that same directory.
This is useful when your repository contains multiple Python projects but only one of them should be deployed by this Phemeral project.
## Trigger a New Deployment [#trigger-a-new-deployment]
The updated root directory is used for **new** deployments. Existing deployments keep the configuration they were built with.
To apply the change:
* **With GitHub CD**: Push a new commit to a mapped branch.
* **Without GitHub CD**: Create a new deployment from the dashboard.
## Clear the Custom Root Directory [#clear-the-custom-root-directory]
To return to autodetection from the repository root:
1. Open the project's **Settings** tab.
2. In **Root Directory**, remove the saved value.
3. Click **Save Root Directory**.
When the saved value is empty, Phemeral falls back to autodetecting the project root from the repository root. The section shows the project as using **Autodetect**.
## Notes [#notes]
* The directory is repository-relative, not an absolute filesystem path.
* If the saved directory does not exist in a future commit, that deployment will fail during project detection.
* A custom root directory only changes where Phemeral looks for dependency files and the app entry point. It does not change your repository contents.
* If you also need to override how the app starts, see [Set a Custom Start Command](/docs/guides/custom-start-command).
# Set a Custom Start Command (/docs/guides/custom-start-command)
Use this guide when your app needs a runtime command different from the one Phemeral detects automatically.
## Before You Begin [#before-you-begin]
* A Phemeral project.
* Access to the project's **Settings** tab.
* A start command that binds your app to port `8000`.
Phemeral saves the custom start command at the **project** level. New deployments for that project use the saved command until you clear it.
## When to Use a Custom Start Command [#when-to-use-a-custom-start-command]
Most projects should keep autodetection enabled. Set a custom command only when you need to override the default `uvicorn` or `gunicorn` command that Phemeral derives from your app.
Common cases include:
* Your app starts through a wrapper script.
* You need different runtime flags than the defaults.
* Your app entry point is valid, but the detected server command is not the one you want to run.
* A monorepo where you want to specify which service within the repo to run.
## Save a Custom Start Command [#save-a-custom-start-command]
1. Open your project in the dashboard.
2. Go to the **Settings** tab.
3. Find the **Start Command** section.
4. Enter the command you want Phemeral to run inside the deployment VM.
5. Click **Save Command**.
After the command is saved, the section shows the project as using a **Custom** start command.
## Trigger a New Deployment [#trigger-a-new-deployment]
The updated command is used for **new** deployments. Existing deployments keep the command they were built with.
To apply the change:
* **With GitHub CD**: Push a new commit to a mapped branch.
* **Without GitHub CD**: Create a new deployment from the dashboard.
## Clear the Custom Command [#clear-the-custom-command]
To return to autodetection:
1. Open the project's **Settings** tab.
2. In **Start Command**, remove the saved value.
3. Click **Save Command**.
When the saved value is empty, Phemeral falls back to its autodetected runtime command. The section shows the project as using **Autodetect**.
## Example Commands [#example-commands]
```bash
# FastAPI or Django
uvicorn app.main:app --host 0.0.0.0 --port 8000
# Flask
gunicorn app.main:app --bind 0.0.0.0:8000
```
## Notes [#notes]
* The command should start a web server process that binds to port `8000`. Phemeral routes incoming requests to that port.
* If you clear the command later, future deployments go back to using the autodetected default. See [Supported Frameworks](/docs/reference/supported-frameworks).
# Manage Environment Variables (/docs/guides/environment-variables)
Use environment variables to pass configuration and secrets to your application without hardcoding them in your source code. Each environment has its own independent set of variables.
## Before You Begin [#before-you-begin]
* Environment variable values must be non-empty.
* Each environment can have up to **200 environment variables**.
* Changes apply to new deployments. Existing deployments keep the values they were built with.
## Add Variables During Project Creation [#add-variables-during-project-creation]
1. From the dashboard, click **New Project**.
2. Complete the project details until you reach **Environment Variables**.
3. Use the environment selector to choose the variable group you want to edit. **Production** is selected by default.
4. Click **Add variable**, then enter a key and value.
5. Switch between **Production**, **Staging**, and **Development** to add variables to the other environment groups.
6. Click **Create Project**, or continue to the advanced settings before creating the project.
## Add Variables While Creating an Environment [#add-variables-while-creating-an-environment]
1. Open the project's **Environments** page.
2. Click **New Environment**.
3. Enter the environment name.
4. Under **Environment variables (optional)**, click **Add variable** and enter a key and value.
5. Click **Create environment**.
## Manage an Existing Environment [#manage-an-existing-environment]
1. Open the environment in the dashboard.
2. In **Environment Variables**, click **Manage Env Vars**.
3. In the side panel, edit existing keys or values, click **Add variable** to add a row, or use the remove button beside a row to delete it.
4. Review the complete variable set.
5. Click **Save changes**.
The side panel loads the environment's complete variable set.
Closing the side panel or clicking **Cancel** discards unsaved changes.
## Import a `.env` File or Snippet [#import-a-env-file-or-snippet]
You can import variables during project creation, while creating an environment, or from an existing environment's management panel.
1. Select the environment or environment group you want to populate.
2. Click **Import from .env**.
3. Click **Choose file** to select a local `.env` file, or paste `.env` content into the text area.
4. Leave **Override value of existing env vars with imported env vars** unchecked, or select it to replace existing values:
| Setting | Matching existing keys | New keys |
| ---------------------------- | -------------------------------------------------- | ------------------------- |
| Override unchecked (default) | Keep the existing value | Add the imported variable |
| Override checked | Replace the existing value with the imported value | Add the imported variable |
5. Click **Import env vars**.
6. Review the populated form, then save or submit the parent form.
Importing only changes the current form draft; no variables are saved until you submit the parent form.
Imported files and pasted content must be no larger than **1 MB**, and an import cannot bring the selected environment above its 200-variable limit.
## Key Format Requirements [#key-format-requirements]
Environment variable keys must:
* Start with a letter (`a-z`, `A-Z`) or underscore (`_`).
* Contain only letters, digits (`0-9`), and underscores.
* Be unique within the environment.
Valid examples include `DATABASE_URL`, `SECRET_KEY`, `_INTERNAL_FLAG`, and `API_KEY_V2`.
Every variable with a key must have a non-empty value.
## View a Variable's Value [#view-a-variables-value]
Values in the environment summary are hidden by default:
1. Open the environment in the dashboard.
2. In **Environment Variables**, click the reveal control beside the variable you want to inspect.
Opening **Manage Env Vars** retrieves the current values and displays them in editable fields.
## Redeploy After Changes [#redeploy-after-changes]
After you add, change, or remove a variable, create a new deployment for the change to take effect:
* **With GitHub CD**: Push a commit to the mapped branch.
* **Without GitHub CD**: Create a new deployment from the dashboard.
# Set Up GitHub Continuous Deployment (/docs/guides/github-integration)
This guide covers how to set up continuous deployment so that pushing to a GitHub branch automatically deploys your code to a Phemeral environment.
## Prerequisites [#prerequisites]
* A Phemeral project. See [Deploy Your First Project](/docs/getting-started/first-deployment) if you haven't created one.
* A [connected GitHub account](/docs/getting-started/connect-github) with the Phemeral GitHub App installed.
## Connect a Repository to Your Project [#connect-a-repository-to-your-project]
1. Open your project in the dashboard.
2. Go to the **Settings** tab.
3. In the **GitHub Repository** section, select the repository from the dropdown.
The dropdown lists all repositories that Phemeral has access to across your GitHub account and any of your GitHub organizations where Phemeral has been connected.
A project can be connected to one repository at a time.
## Map a Branch to an Environment [#map-a-branch-to-an-environment]
After connecting a repository:
1. On the **Settings** tab, find the **Branch Mappings** section.
2. Select a **branch** from the repository.
3. Select the **environment** you want that branch to deploy to.
4. Save the mapping.
You can map multiple branches to different environments within the same project. For example:
| Branch | Environment |
| ---------------------- | ----------- |
| `main` | Production |
| `pre-release` | Staging |
| `fancy-feature-branch` | Development |
Each branch can be mapped to one environment. Each environment can have one branch mapped to it.
## Remove a Branch Mapping [#remove-a-branch-mapping]
To stop automatic deployments for a branch:
1. Go to the project's **Settings** tab.
2. Find the branch mapping you want to remove.
3. Delete the mapping.
Existing deployments are not affected. The environment retains its current deployment.
## Disconnect a Repository [#disconnect-a-repository]
To remove the repository connection entirely:
1. Go to the project's **Settings** tab.
2. Click **Disconnect** in the GitHub Repository section.
This removes **all** branch-to-environment mappings for the project. Existing deployments and environments are not affected, but no new automatic deployments will be triggered until a repository is reconnected.
# Create and Connect to a Database Cluster (/docs/guides/managed-postgres)
A **database cluster** is a fully managed Postgres database that lives inside one of your projects. This guide walks through creating a cluster, retrieving its connection string, connecting your application, and deleting the cluster when you no longer need it.
For background on how clusters scale and how they are billed, see [Database Clusters](/docs/concepts/database-clusters) and the [Managed Postgres reference](/docs/reference/managed-postgres).
## Prerequisites [#prerequisites]
* An organization on the **Pro** plan.
* A Phemeral project.
## Create a Database Cluster [#create-a-database-cluster]
1. Open your project in the dashboard.
2. Go to the **Database Clusters** tab.
3. Click **New Cluster**.
4. Enter a **cluster name**. Names may contain letters, numbers, spaces, and hyphens, and must be unique within the project.
5. Click **Create Cluster**.
Phemeral provisions the cluster and it appears in the project's cluster list. A project can hold up to **20 database clusters**.
## Get the Connection String [#get-the-connection-string]
Each cluster exposes a **connection URI** that you can use to connect to your cluster.
1. Open the project's **Database Clusters** tab and select the cluster.
2. On the cluster's detail page, find the **Connection URI** field.
3. Click the reveal (eye) button to display the connection string.
The **pooled connection string** is selected by default and is what you should use for most applications. It supports up to **10,000 concurrent connections** and lets you connect directly without running your own connection pooler.
If you need a **direct connection string** instead (for example, for administrative tools or long-running sessions), you can uncheck the **Pooled connection URI** option before revealing the string.