> ## Documentation Index
> Fetch the complete documentation index at: https://developer.upsun.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Migrating from another provider to Upsun

> Learn how to migrate an application hosted on another provider to Upsun so it is ready to deploy.

export const VariableBlock = ({name}) => {
  return <var spellCheck={false} title={`Replace '${name}' with your own data`}>{name}</var>;
};

This guide explains how to migrate an existing application from another hosting provider to Upsun.

It focuses on the technical steps required to make your application deployable on Upsun, including
configuration, services, environment variables, and data migration.

No prior experience with Upsun is needed — each step is explained simply, with examples and troubleshooting tips.

## Before you begin

You need:

* An understanding of the main [Upsun concepts](/docs/core-concepts)
* An Upsun account.
  If you don't already have one, <a class="link" href="https://auth.upsun.com/register/">register for a trial account</a>.
  You can sign up with an email address or an existing GitHub, Bitbucket, or Google account.
  If you choose one of these accounts, you can set a password for your Upsun account later.
* The [Upsun CLI](/cli) installed locally

Follow the steps below to begin the migration of your project.

## 1. Audit your data from your current project

Before migrating, make sure you have access to:

* Your source code
* Your database
* Your assets and uploaded files

<Tabs>
  <Tab title="From Self-Managed">
    **Runtime & build**

    * **Runtime version**: language and version in use (Node.js, Python, Ruby, PHP, etc.)
    * **Package manager**: npm, yarn, pnpm, pip, composer, bundler, etc.
    * **System dependencies**: packages installed via `apt`, `yum`, or similar
    * **Build process**: how assets are compiled, if any (webpack, vite, sass, etc.)
    * **How the app starts**: systemd unit, supervisor config, pm2, Docker entrypoint, etc.
    * **Reverse proxy**: nginx, Apache, or Caddy config (rewrites, headers, timeouts, SSL termination)

    **Processes & scheduling**

    * **Background workers**: how they are started and supervised
    * **Cron jobs**: run `crontab -l` to list all scheduled tasks

    **Environment & secrets**

    * **Environment variables**: run `env` on your server to list them
    * **`.env` files**: check for any local env files used at runtime
    * **SSL certificates**: Let's Encrypt, manual certs, or managed by proxy

    **Data & storage**

    * **Database engine and version**: PostgreSQL, MySQL, MongoDB, etc.
    * **Writable folders**: directories your app writes to at runtime (uploads, cache, logs)
    * **Backup strategy**: how and where backups are currently stored

    **Access**

    * **Users and teams**: who currently has access to the server and application
    * **SSH access**: confirm you can connect to export data
  </Tab>

  <Tab title="From Heroku">
    **App/runtime/build**

    * **Stack & runtime versions**: current stack (`heroku stack`), Node/Python/Ruby/etc versions, package manager (npm/yarn/pnpm), locked deps.
    * **Slug/build behavior**: anything relying on Heroku's slug compilation quirks, `postinstall`, `release` phase, `heroku-postbuild`.
    * **Build vs run separation**: what gets generated at build time (assets, SSR bundles) vs needs runtime write access.

    **Processes, jobs, scheduling**

    * **Release phase scripts** (Procfile `release`): DB migrations, cache warmups, etc.
    * **Heroku Scheduler** jobs (often forgotten) + any custom cron-like jobs.
    * **Workers/queues**: what queue system (Redis/Rabbit/etc), concurrency settings, retry policies.

    **Networking, routing, and platform features**

    * **Routes/HTTP behavior**: any reliance on Heroku router timeouts, request body size limits, websockets, sticky sessions (rare), streaming.
    * **Outbound networking**: external integrations with IP allowlists; need for stable egress IPs.
    * **SSL/TLS details**: ACM vs manual certs, SNI endpoints, any HSTS / security headers configured elsewhere (CDN/WAF).

    **Data & state**

    * **Datastores & backups**: Postgres plan/features (extensions, follower, PITR), Redis plan, backup/restore flows, retention.
    * **File storage**: any use of ephemeral filesystem (tmp/uploads) that should be moved to object storage.
    * **Caches**: in-memory assumptions, Redis usage patterns, cache invalidation strategy.

    **Observability & ops**

    * **Logging drains**: Papertrail/Datadog/Splunk drains + formats, PII controls.
    * **Metrics/APM**: add-ons and config, alert rules, SLOs.
    * **Error tracking**: Sentry/Rollbar, release tagging.

    **Delivery and environments**

    * **Pipelines & review apps**: how staging/prod are promoted, config var diffs, Heroku CI.
    * **GitHub integration**: auto-deploy branches, required checks.
    * **Regions**: app region + data region alignment, compliance constraints.

    **Access & governance**

    * **SSO / permissions model**: Enterprise features, team roles, API tokens in CI.
    * **Secrets handling**: where secrets live (Heroku config vars, CI, Vault), rotation plan.
  </Tab>

  <Tab title="From Vercel">
    **Project structure & build**

    * **Framework + version** (Next.js, Nuxt, SvelteKit, etc.) and Vercel build preset.
    * **Build & Output settings**: build command, install command, output directory, ignored build step.
    * **Monorepo setup**: root directory, workspace tool (pnpm/yarn/npm), Turbo/Nx config, package manager version.
    * **Node/runtime versions**: Node version, edge runtime usage, any experimental flags.

    **Routing & edge behavior (must map cleanly)**

    * **Rewrites/redirects/headers** (`vercel.json` / `next.config`): including regex rules and priority order.
    * **Middleware usage** (Next.js middleware): what it does (auth, geo, A/B, rewrites).
    * **Edge Functions** vs **Serverless Functions**: which endpoints run where and why.
    * **Regional settings**: functions/edge regions and latency expectations.

    **Rendering model**

    For Next.js especially, inventory exactly which parts are:

    * **SSG** pages
    * **SSR** pages
    * **ISR** pages (revalidate timings, on-demand revalidation hooks)
    * **Route Handlers / API routes**
    * **Image Optimization** (`next/image`) usage

    This determines whether you need a long-running web process, background jobs, cache, and/or a CDN strategy.

    **Environment variables & secrets**

    * **Env vars per environment** (Production / Preview / Development) and which are "encrypted" / "sensitive".
    * **Preview env overrides**: anything that only exists on preview deployments.
    * **Secret sources**: Vercel integrations, Vercel-managed secrets, external vaults.

    **Storage & state (Vercel add-ons / managed services)**

    * **Vercel Postgres / KV / Blob** usage, connection methods, pooling, migrations.
    * **Any external DB** (Supabase/RDS/etc): connection limits, pooling, IP allowlists.
    * **File uploads**: where do uploads go (Blob/S3/etc)? Any code writing to local disk (won't persist).

    **Scheduled and async work**

    * **Vercel Cron Jobs**: schedules, endpoints called, auth strategy.
    * **Background processing**: do you rely on queueing elsewhere? Any long-running tasks incorrectly placed in serverless functions?

    **Limits & performance assumptions**

    * **Function timeouts/memory** assumptions (serverless) and payload size constraints.
    * **Caching strategy**: Vercel/CDN cache headers, Next fetch caching, ISR cache behavior.
    * **Build cache** expectations and cold-start sensitivity.

    **Domains, deploys, and release workflow**

    * **Domains + redirects + canonical host** rules, wildcard domains, multiple apps behind one domain.
    * **Preview deployments**: how they're used (QA, PR checks), who needs access, protected previews.
    * **Git integration**: which repos/branches deploy, required checks, auto-promote patterns, deploy hooks/webhooks.

    **Observability & access**

    * **Logs/analytics**: Vercel Analytics, Speed Insights, log drains (if any), retention needs.
    * **Team access**: members, roles, SSO, tokens used by CI/CD.
  </Tab>
</Tabs>

### How Upsun maps to your existing architecture

When migrating from another platform, map your existing components to Upsun concepts.

<table>
  <thead>
    <tr>
      <th>Existing platform concept</th>
      <th>Upsun equivalent</th>
    </tr>
  </thead>

  <tbody>
    <tr>
      <td>Web dyno / server</td>
      <td><a href="/docs/core-concepts/structure#apps">Application Container</a></td>
    </tr>

    <tr>
      <td>Worker dyno</td>
      <td><a href="/docs/configure-apps/image-properties/workers">Worker</a></td>
    </tr>

    <tr>
      <td>Add-on database</td>
      <td><a href="/docs/add-services">Service</a></td>
    </tr>

    <tr>
      <td>Environment variables</td>
      <td><a href="/docs/development/variables">Environment variables</a></td>
    </tr>

    <tr>
      <td>Upload storage</td>
      <td><a href="/docs/configure-apps/image-properties/mounts">Mounts</a></td>
    </tr>

    <tr>
      <td>Cron jobs / Heroku Scheduler</td>
      <td><a href="/docs/configure-apps/image-properties/crons">Crons</a></td>
    </tr>

    <tr>
      <td>Domains</td>
      <td><a href="/docs/routes">Routes</a></td>
    </tr>

    <tr>
      <td>Buildpacks</td>
      <td><a href="/docs/configure-apps/image-properties/hooks">Build hooks</a></td>
    </tr>

    <tr>
      <td>Review apps / preview deployments</td>
      <td><a href="/docs/glossary#preview-environment">Preview environments</a></td>
    </tr>

    <tr>
      <td>SSL certificates</td>
      <td><a href="/docs/routes/https#tls-certificates">Automatic TLS</a> (managed)</td>
    </tr>
  </tbody>
</table>

## 2. Clone your Git repository locally

As a start, you need to clone your source code locally to make it Upsun ready.

```bash theme={null}
git clone <REPOSITORY_URL> your-app-directory
cd your-app-directory
```

## 3. Initialize Upsun configuration

A Upsun project is configured through the `.upsun/config.yaml` file.
This file defines your applications, services, routes, and runtime configuration.

Upsun provides a [CLI `project:init` command](/cli/init).

```bash theme={null}
upsun project:init
```

This command initializes your Upsun project configuration.
If you choose `With AI (automatic)`, it detects your app's requirements and creates a config file for you.

## 4. Create a new Upsun project

<Tabs>
  <Tab title="Using the CLI">
    If you do not already have an organization created on Upsun, create one:

    ```bash theme={null}
    upsun org:create
    ```

    Then run the following command to create a project:

    ```bash theme={null}
    upsun project:create
    ```

    When prompted, fill in details like the project name, [region](/docs/development/regions), and the name of your organization.
  </Tab>

  <Tab title="Using the Console">
    [Create a new project from scratch](https://console.upsun.com/org/create-project/info).

    If you do not already have an organization created to put the project, you'll first be instructed to create one.

    Once you have done so, select that organization from the dropdown, and select **Create from scratch**.

    In the form, fill in details like the project name and [region](/docs/development/regions).
    You'll be able to define resources for the project after your first push.
  </Tab>
</Tabs>

<Info>
  Before migrating your production environment, we recommend pushing to a separate
  branch first. Upsun automatically creates a [preview environment](/docs/glossary#preview-environment) for
  each branch, allowing you to validate your configuration, services, and data
  before switching any production traffic.
</Info>

## 5. Configure services and start commands

### Configure your services

In your Upsun project, you can add as many services as you need.

List your current services in use and add them in the configuration, following the corresponding [Service page](/docs/add-services#available-services).

As an example, if your current project is using [PostgreSQL](/docs/add-services/postgresql) and [Redis](/docs/add-services/redis),
edit your `.upsun/config.yaml` file and add the following:

<Tabs>
  <Tab title="Using default endpoints">
    ```yaml title=".upsun/config.yaml" theme={null}
    applications:
      myapp:
        relationships:
          database:
          cache:
    services:
      database:
        type: postgresql:16
      cache:
        type: redis:7.2
    ```
  </Tab>

  <Tab title="Using explicit endpoints">
    ```yaml title=".upsun/config.yaml" theme={null}
    applications:
      myapp:
        relationships:
          database:
            service: postgresql_service
            endpoint: postgresql
          cache:
            service: redis_service
            endpoint: redis
    services:
      postgresql_service:
        type: postgresql:16
      redis_service:
        type: redis:7.2
    ```
  </Tab>
</Tabs>

<Info>
  You need to declare your services in the `services` top YAML key and add a [`relationships`](/docs/configure-apps/image-properties/relationships) for each service in your
  `myapp` configuration. [Service environment variables](/docs/development/variables#service-environment-variables) will be automatically injected in your `myapp` container to interact with.
</Info>

### Configure how your application and workers start

<Tabs>
  <Tab title="From Self-Managed">
    Find out how your current application is started
    and convert it to an Upsun configuration.

    * How you start your runtime should go in `myapp.web.commands.start`
    * How you start your worker should go in `myapp.workers.<WORKER_NAME>.commands.start`

    Example:

    ```yaml title=".upsun/config.yaml" theme={null}
    applications:
      myapp:
        type: "python:3.12"
        web:
          commands:
            start: "gunicorn app:app --workers 4 --bind 0.0.0.0:$PORT"
        workers:
          celery:
            commands:
              start: "celery -A tasks worker --loglevel=info"
    ```
  </Tab>

  <Tab title="From Heroku">
    Heroku applications typically define processes in a `Procfile`.

    On Upsun, these processes are defined in `.upsun/config.yaml`
    using the [`web` section](/docs/configure-apps/image-properties/web) for the HTTP entrypoint and
    [`workers`](/docs/configure-apps/image-properties/workers) for background processes.

    Transform your process definitions. If your Procfile has:

    ```yaml title="Procfile" theme={null}
    web: gunicorn app:app --workers 4
    worker: celery -A tasks worker --loglevel=info
    ```

    Your `.upsun/config.yaml` should include these commands in the `commands.start` section:

    ```yaml title=".upsun/config.yaml" theme={null}
    applications:
      myapp:
        type: "python:3.12"
        web:
          commands:
            start: "gunicorn app:app --workers 4 --bind 0.0.0.0:$PORT"
        workers:
          celery:
            commands:
              start: "celery -A tasks worker --loglevel=info"
    ```
  </Tab>

  <Tab title="From Vercel">
    Applications deployed on Vercel often rely on serverless functions and edge features.

    On Upsun, these workloads typically run as a persistent web process
    inside an application container. Unlike serverless functions, the process stays alive
    between requests, which changes how you think about memory, state, and concurrency.

    Identify the main entrypoint of your application.

    For example, a Next.js application usually runs with:

    ```bash theme={null}
    npm run start
    ```

    You can define this command in `.upsun/config.yaml`:

    ```yaml title=".upsun/config.yaml" theme={null}
    applications:
      myapp:
        type: "nodejs:20"
        web:
          commands:
            start: "npm run start"
    ```

    If your project includes background jobs or queue consumers, define them as workers:

    ```yaml title=".upsun/config.yaml" theme={null}
    applications:
      myapp:
        workers:
          jobs:
            commands:
              start: "node worker.js"
    ```

    You may also need to review features that rely on Vercel platform behavior such as:

    * Edge middleware
    * Serverless API routes
    * Incremental static regeneration (ISR)
    * Vercel image optimization

    These features may require application-level implementations when running on Upsun.
  </Tab>
</Tabs>

## 6. Configure build and deploy hooks

If you have custom build steps, define them explicitly in the `hooks.build` and `hooks.deploy` section:

```yaml title=".upsun/config.yaml" theme={null}
applications:
  myapp:
    hooks:
      build: |
        pip install -r requirements.txt
        python manage.py collectstatic --noinput
      deploy: |
        python manage.py migrate --noinput
```

<Warning>
  The app container is fully writable during the `build` hooks and is read-only during the `deploy` hooks.
  During the `deploy` hooks, only defined [mounts](/docs/configure-apps/image-properties/mounts) are writable.
</Warning>

## 7. Define mounts

Define your [mounts](/docs/configure-apps/image-properties/mounts) (writable folders) in `.upsun/config.yaml`:

```yaml title=".upsun/config.yaml" theme={null}
applications:
  myapp:
    mounts:
      'web/uploads':
        source: storage
        source_path: uploads
      'private':
        source: instance
        source_path: private
```

Refer to [supported mount types](/docs/configure-apps/image-properties/mounts#define-a-mount) for more information.

## 8. Define routes

If you are migrating a [multi-application project](/docs/configure-apps/multi-app), or want to customize how your application is served,
you need to [configure routes](/docs/routes).

## 9. Optional: Define a resource initialization strategy

By default, when you first deploy your project,
Upsun allocates [default resources](/docs/manage-resources/resource-init) to each of your containers.
If you don't want to use those default resources,
define your own [resource initialization strategy](/docs/manage-resources/resource-init#specify-a-resource-initialization-strategy) before pushing your code.

Alternatively, you can [amend those default container resources](/docs/manage-resources/adjust-resources) after your project is deployed.

## 10. Optional: Add environment variables

If your app requires environment variables to build properly, [add them to your environment](/docs/development/variables/set-variables).

Extract existing environment variables from your project:

<Tabs>
  <Tab title="From Self-Managed">
    SSH to your server and use the `env` CLI command to list all your existing environment variables:

    ```bash theme={null}
    ssh <YOUR-SERVER-IP>
    env
    ```
  </Tab>

  <Tab title="From Heroku">
    List your Heroku environment variables using the CLI:

    ```bash theme={null}
    heroku config
    ```
  </Tab>

  <Tab title="From Vercel">
    List your Vercel environment variables using the CLI:

    ```bash theme={null}
    vercel env ls
    ```

    You can retrieve the value of a variable with:

    ```bash theme={null}
    vercel env pull
    ```

    This command writes environment variables to a `.env` file locally.
  </Tab>
</Tabs>

Review the variables and recreate them in Upsun using [`variable:create`](/cli/reference#variablecreate).

```bash theme={null}
# Standard environment variables
upsun variable:create --level environment --name env:<KEY> --value <VALUE>

# Project-wide variables
upsun variable:create --level project --name env:<KEY> --value <VALUE>

# Application-specific variables
upsun variable:create --app-scope myapp --name env:<KEY> --value <VALUE>
```

<Info>
  For sensitive values, be sure to add the `--sensitive true` option to avoid exposing any confidential information.
</Info>

## 11. Push your changes

The way to push your code to Upsun depends on
whether you're hosting your code with a third-party service using a [source integration](/docs/integrations/source).
If you aren't, your repository is hosted in Upsun
and you can use the CLI or just Git itself.

<Info>
  At this stage, ensure you've already committed your updated files (mainly `.upsun/config.yaml`) in your Git history:

  ```bash theme={null}
  git add .upsun/config.yaml
  git commit -m "Add Upsun configuration file"
  ```
</Info>

<Tabs>
  <Tab title="Using the CLI">
    1. (Optional) Get your project ID by running the following command:

       ```bash theme={null}
       upsun projects
       ```

    2. (Optional) Add Upsun as a remote repository by running the following command:

       ```bash theme={null}
       upsun project:set-remote <PROJECT_ID>
       ```

    3. Push to the Upsun repository by running the following command:

       ```bash theme={null}
       upsun push
       ```

    When you try to push, any detected errors in your configuration are reported and block the push.
    After any errors are fixed, a push creates a new environment.
  </Tab>

  <Tab title="Using a source integration">
    Set up the integration for your selected service:

    * [Bitbucket](/docs/integrations/source/bitbucket)
    * [GitHub](/docs/integrations/source/github)
    * [GitLab](/docs/integrations/source/gitlab)

    Then push code to that service as you do normally.
    Pushing to a branch creates an environment from that branch.

    Note that the source integration doesn't report any errors in configuration directly.
    You have to monitor those in your project activities.
  </Tab>

  <Tab title="Using Git">
    1. Add an [SSH key](/docs/development/ssh/ssh-keys).

    2. In the Console, open your project and click **Code**.

    3. Click **Git**.

    4. From the displayed command, copy the location of your repository.
       It should have a format similar to the following:

       ```text theme={null}
       abcdefgh1234567@git.eu.upsun.com:abcdefgh1234567.git
       ```

    5. Add Upsun as a remote repository by running the following command:

       ```bash theme={null}
       git remote add upsun <REPOSITORY_LOCATION>
       ```

    6. Push to the Upsun repository by running the following command:

       ```bash theme={null}
       git push -u upsun <DEFAULT_BRANCH_NAME>
       ```

    When you try to push, any detected errors in your configuration are reported and block the push.
    After any errors are fixed, a push creates a new environment.
  </Tab>
</Tabs>

<Info>
  If your application is deployed without error but you get a 502 error when loading your application, [refer to the Troubleshoot page](/docs/troubleshooting/general).
</Info>

## 12. Test your production environment

When your Upsun project is successfully deployed:

* **Verify service connections**:
  * Check database connectivity
  * Verify cache operations
  * Test background worker execution
* **Load testing**: Run a load test against your Upsun environment
  before switching DNS to validate performance under realistic traffic.
  Tools like [k6](https://k6.io), [Locust](https://locust.io), or
  [Gatling](https://gatling.io) can be used for this purpose.
* **Review logs and metrics**:

```bash theme={null}
upsun logs app
upsun metrics:all
```

* **Verify functionality**:
  * Test critical user flows
  * Confirm integrations working
  * Check scheduled jobs executing

## 13. Enable maintenance mode

Before importing data and switching DNS, enable maintenance mode in your application if it supports it.
This prevents users from writing new data to your old environment during the cutover, avoiding data loss or inconsistencies.

<Warning>
  Do not skip this step if your application is live and receiving traffic. Any writes to your old environment after the database export will be lost.
</Warning>

## 14. Import data

Once you have an environment ready and maintenance mode is enabled, import the data from your current provider.
The exact process depends on the database engine you use.

<Tabs>
  <Tab title="From Self-Managed">
    Depending on the database engine you're using, download a dump of your database into a SQL file locally
    and import it into your application container.
  </Tab>

  <Tab title="From Heroku">
    **Option 1**: Export as SQL directly (recommended)

    ```bash theme={null}
    DATABASE_URL=$(heroku config:get DATABASE_URL)
    pg_dump -Fp --no-owner --clean --if-exists $DATABASE_URL > database.sql
    ```

    **Option 2**: If you have an existing custom format backup

    ```bash theme={null}
    heroku pg:backups:capture
    heroku pg:backups:download
    pg_restore -f database.sql --no-owner --clean --if-exists latest.dump
    ```
  </Tab>

  <Tab title="From Vercel">
    If your Vercel project uses an external database (for example Supabase, Neon, or PlanetScale),
    export the database using the appropriate tool for your database engine.

    For PostgreSQL:

    ```bash theme={null}
    pg_dump -Fp --no-owner --clean DATABASE_URL > database.sql
    ```

    For MySQL:

    ```bash theme={null}
    mysqldump --single-transaction DATABASE_NAME > database.sql
    ```
  </Tab>
</Tabs>

Then import the dump using the Upsun CLI:

```bash theme={null}
upsun sql < <BACKUP_FILE_NAME>
```

<Info>
  If you have multiple database services, target a specific one with `--relationship=<RELATIONSHIP_NAME>`.
</Info>

For any potential more details, see the [specific service documentation](/docs/add-services).

## 15. Import files

Your app may include content files, meaning files that aren't intended to be part
of your codebase and therefore aren't tracked in Git.

You can upload such files to [mounts you created](/docs/configure-apps/image-properties/mounts).

Assuming you have the following mounts:

```yaml title=".upsun/config.yaml" theme={null}
applications:
  myapp:
    mounts:
      'web/uploads':
        source: storage
        source_path: uploads
      'private':
        source: instance
        source_path: private
```

Upload each mount separately:

```bash theme={null}
upsun mount:upload --mount web/uploads --source ./uploads
upsun mount:upload --mount private --source ./private
```

Alternatively, you can transfer files using an [SSH client](/docs/development/file-transfer#transfer-files-using-an-ssh-client).

## 16. Configure your domain and update DNS records

### Lower your TTL in advance

<Warning>
  Before switching DNS, lower your domain's TTL to 300 seconds (5 minutes) at least 24 hours in advance.
  This reduces propagation delay during cutover and makes it easier to roll back quickly if needed.
</Warning>

Add your domain to Upsun:

```bash theme={null}
upsun domain:add www.yourDomain.com
```

Get your Upsun target URL:

```bash theme={null}
upsun environment:url
```

### Update your DNS records

Add a `CNAME` record in your DNS provider pointing your domain to the URL returned above.

Once DNS has propagated, verify your domain resolves correctly and your application loads as expected before disabling maintenance mode.

<Info>
  DNS propagation can take up to 48 hours depending on your provider and previous TTL value.
  You can monitor propagation using a tool like dnschecker.org.
</Info>

### Rollback plan

If something goes wrong after the DNS switch, you can revert quickly:

* Point your `CNAME` back to your old provider's URL
* Re-disable maintenance mode on your old environment
* Investigate the issue on Upsun before retrying

Keep your old environment live and intact until you have fully validated the migration.

## 17. Invite teams and users

You can either invite individual users to your project, or create teams and then invite users to teams (recommended).

### Create a team and invite users

We recommend creating a team and inviting individual users to it, as you can manage access at the team level instead of one-by-one.

When creating a team for a project, a role is required:

* At the Project level: `admin` or `viewer`
* For each environment type (`production`, `staging` and `development`): `admin`, `contributor` or `viewer`

To create a team, you can either use the Console or the CLI:

```bash theme={null}
upsun team:create --role viewer,production:viewer,staging:contributor,development:admin --label "My team"
```

To invite a user to a team, provide the user ID (if existing user) or the email address:

```bash theme={null}
upsun team:user:add <USER_EMAIL_ADDRESS_OR_ID>
```

<Info>
  Each user invited to a team inherits the team's role.
</Info>

### Invite individual users

When inviting individual users on a project, a role is required:

* At the [Project level](/docs/administration/users#project-roles): `admin` or `viewer`
* For each [Environment type](/docs/administration/users#environment-type-roles) (`production`, `staging` and `development`): `admin`, `contributor` or `viewer`

To invite individual users on a project, use the following CLI command:

```bash theme={null}
upsun user:add --role viewer,production:viewer,staging:contributor,development:admin <USER_EMAIL_ADDRESS>
```

## 18. Monitor your application

Once your application is live, make sure to check out the [continuous profiling](/docs/observability) feature
to ensure your application is running as expected.

## Troubleshooting common migration issues

If you encounter any error during the migration, refer to the [Troubleshoot page](/docs/troubleshooting/general).
