Create apps

Control your apps and how they’re built and deployed on with YAML configuration.


Within a single project, you can have one or more app and each app can have multiple instances. Instances are where the same code can be run with different configurations, such as one for external communication and one for background processes. All of the apps and instances are configured with the same syntax. You can find a complete reference of all possible settings.

A minimal application 

To create a very basic app, you need a few things:

  • A unique name not shared by any other app in the project.
  • The runtime type defining what language it uses.
  • A disk size for your deployed files.
  • A definition of how to handle requests from the outside web.

The following example shows such a basic setup for PHP:

# The name of this application, which must be unique within the project.
name: 'app'

# The language and version for your app.
type: 'php:8.0'

# The size of the app's persistent disk (in MB).
disk: 2048

# The app's configuration when it's exposed to the web.
            # The public directory relative to the app root.
            root: 'web'
            # The front-controller script which determines where to send non-static requests.
            passthru: '/app.php'

Use multiple apps 

You might have multiple apps you want to run from a single Git repository, such as a RESTful web service and a front-end or a main website and a blog. In such cases, you configure each app separately and define the relationships among them. See the various ways to set up a multi-app project.

Connect to services 

If you want to use one of the databases or other services provides, set it up by following these steps:

  1. Configure the service based on the documentation for that service.
  2. Use the information from that service inside your app’s relationships definition to configure how your app communicates with the service.

Control the build and deploy process 

Your app generally needs to undergo some steps to be turned from the code in your Git repository into a running app. If you’re running a PHP or Node.js app, this starts with the build flavor, which runs a default set of tasks. Then any global dependencies can be installed.

Once these optional tasks are done, you can run hooks at various points in the process. Hooks are places for your custom scripts to control how your app is built and deployed.

Configure what’s served 

Once your app is built, it needs a defined way to communicate with the outside world. Define its behavior with a web instance. There you can set what command runs every time your app is restarted, how dynamic requests are handled, and how to respond with static files.

Response compression 

Response compression reduces payload sizes and generally increases your app’s response times. Dynamic responses generated by your app aren’t compressed because of a general security issue. While your app can compress its own response, doing so when the response includes any user-specific information, including a session cookie, opens up an attack vector over SSL/TLS connections. For that reason, you generally shouldn’t compress generated responses.

Requests for static files that are served directly by are compressed automatically using either gzip or Brotli compression if:

  • The request headers for the file support gzip or Brotli compression.
  • The file is served directly from disk by and not passed through your application.
  • The file would be served with a cache expiration time in the future.
  • The file type is one of: HTML, JavaScript, JSON, PDF, PostScript, SVG, CSS, CSV, plain text, or XML.

Also, if there is a request for a file and another file exists with the same name plus a .gz or .br extension, the compressed file is served regardless of the original file type. So a request for styles.css that accepts a gzipped file (according to the request headers) automatically returns a styles.css.gz file if it exists. This approach supports any file type and offers some CPU optimization, especially if the cache lifetime is short.

Comprehensive example 

The following example shows a setup for a PHP app with comments to explain the settings.

# The name of this application, which must be unique within a project.
name: 'app'

# The type key specifies the language and version for your application.
type: 'php:8.0'

# By default, composer 1 will be used. Specify composer 2 in the dependencies to get the latest version
        composer/composer: '^2'

# The relationships of the application with services or other applications.
# The left-hand side is the name of the relationship as it will be exposed
# to the application in the PLATFORM_RELATIONSHIPS variable. The right-hand
# side is in the form `<service name>:<endpoint name>`.
    database: 'mysqldb:mysql'

# The hooks that will be triggered when the package is deployed.
    # Build hooks can modify the application files on disk but not access any services like databases.
    build: |
                                rm web/app_dev.php
    # Deploy hooks can access services but the file system is now read-only.
    deploy: |
                                app/console --env=prod cache:clear

# The size of the persistent disk of the application (in MB).
disk: 2048

# The 'mounts' describe writable, persistent filesystem mounts in the application.
# The keys are directory paths relative to the application root. The values are a
# mount definition. In this case, `web-files` is just a unique name for the mount.
        source: local
        source_path: 'web-files'

# The configuration of the application when it is exposed to the web.
            # The public directory of the application relative to its root.
            root: 'web'
            # The front-controller script which determines where to send
            # non-static requests.
            passthru: '/app.php'
        # Allow uploaded files to be served, but do not run scripts.
        # Missing files get mapped to the front controller above.
            root: 'web/files'
            scripts: false
            allow: true
            passthru: '/app.php'