How to Manage Functions in App Platform

Validated on 23 May 2022 • Last edited on 5 Mar 2026

App Platform is a fully managed Platform-as-a-Service (PaaS) that deploys applications from Git repositories or container images. It automatically builds, deploys, and scales components while handling all underlying infrastructure.

Functions are blocks of code that run on demand without requiring you to provision or manage servers. You can develop on your local machine, test your code from the command line using doctl, then deploy to App Platform without managing the underlying servers.

Add a Function to an App Using Automation

You can add a function to an app using the CLI’s app update command or the API’s app update endpoint. To add a function, update the app spec with the function’s specifications and submit the spec using the following command or endpoint.

How to Add a Function to an App Using the DigitalOcean CLI
  1. Install doctl, the official DigitalOcean CLI.
  2. Create a personal access token and save it for use with doctl.
  3. Use the token to grant doctl access to your DigitalOcean account.
    doctl auth init
  4. Finally, run doctl apps update. Basic usage looks like this, but you can read the usage docs for more details:
    doctl apps update <app id> [flags]
    The following example updates an app with the ID f81d4fae-7dec-11d0-a765-00a0c91e6bf6 using an app spec located in a directory called /src/your-app.yaml. Additionally, the command returns the updated app’s ID, ingress information, and creation date:
    doctl apps update f81d4fae-7dec-11d0-a765-00a0c91e6bf6 --spec src/your-app.yaml --format ID,DefaultIngress,Created
How to Add a Function to an App Using the DigitalOcean API
  1. Create a personal access token and save it for use with the API.
  2. Send a PUT request to https://api.digitalocean.com/v2/apps/{id}.

cURL

Using cURL:

curl -X PUT \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $DIGITALOCEAN_TOKEN" \
"https://api.digitalocean.com/v2/apps/{id}" \
-d '{"alerts":[{"rule":"DEPLOYMENT_FAILED"},{"rule":"DOMAIN_FAILED"}],"domains":[{"domain":"example.com","type":"PRIMARY","zone":"example.com"}],"envs":[{"key":"API_KEY","scope":"RUN_AND_BUILD_TIME","type":"SECRET","value":"EV[1:zqiRIeaaYK/NqctZDYzy6t0pTrtRDez8:wqGpZRrsKN5nPhWQrS479cfBiXT0WQ==]"}],"features":["buildpack-stack=ubuntu-22"],"ingress":{},"name":"example-app","region":"nyc","services":[{"autoscaling":{"max_instance_count":4,"metrics":{"cpu":{"percent":70}},"min_instance_count":2},"git":{"branch":"main","repo_clone_url":"https://github.com/digitalocean/sample-nodejs.git"},"internal_ports":[8080],"log_destinations":[{"name":"your_log_consumer_name","open_search":{"endpoint":"logs.example.com:12345","basic_auth":{"user":"doadmin","password":"1234567890abcdef"},"index_name":"example-index","cluster_name":"example-cluster"}}],"name":"sample-nodejs","run_command":"yarn start","source_dir":"/"}]}'

Python

Using PyDo, the official DigitalOcean API client for Python:

import os
from pydo import Client

client = Client(token=os.environ.get("DIGITALOCEAN_TOKEN"))
req = {
"spec": {
    "name": "web-app-01",
    "region": "nyc",
    "domains": [
        {
            "domain": "app.example.com",
            "type": "DEFAULT",
            "wildcard": True,
            "zone": "example.com",
            "minimum_tls_version": "1.3",
        }
    ],
    "services": [],
    "static_sites": [
        {
            "cors": {
                "allow_origins": [
                    {"exact": "https://www.example.com"},
                    {"regex": "^.*example.com"},
                ],
                "allow_methods": [
                    "GET",
                    "OPTIONS",
                    "POST",
                    "PUT",
                    "PATCH",
                    "DELETE",
                ],
                "allow_headers": ["Content-Type", "X-Custom-Header"],
                "expose_headers": ["Content-Encoding", "X-Custom-Header"],
                "max_age": "5h30m",
                "allow_credentials": False,
            },
            "routes": [{"path": "/api", "preserve_path_prefix": True}],
        }
    ],
    "jobs": [
        {
            "name": "api",
            "gitlab": {
                "branch": "main",
                "deploy_on_push": True,
                "repo": "digitalocean/sample-golang",
            },
            "image": {
                "registry": "registry.hub.docker.com",
                "registry_type": "DOCR",
                "repository": "origin/master",
                "tag": "latest",
            },
            "dockerfile_path": "path/to/Dockerfile",
            "build_command": "npm run build",
            "run_command": "bin/api",
            "source_dir": "path/to/dir",
            "envs": [
                {
                    "key": "BASE_URL",
                    "scope": "BUILD_TIME",
                    "type": "GENERAL",
                    "value": "http://example.com",
                }
            ],
            "environment_slug": "node-js",
            "log_destinations": {
                "name": "my_log_destination",
                "papertrail": {
                    "endpoint": "https://mypapertrailendpoint.com"
                },
                "datadog": {
                    "endpoint": "https://mydatadogendpoint.com",
                    "api_key": "abcdefghijklmnopqrstuvwxyz0123456789",
                },
                "logtail": {
                    "token": "abcdefghijklmnopqrstuvwxyz0123456789"
                },
               "open_search": {
                    "endpoint": "https://myopensearchendpoint.com:9300"
                    "index_name": "logs"
                    "basic_auth": {
                        "user": "doadmin",
                        "password": "password"
                    }
                },
            },
            "instance_count": 2,
            "instance_size_slug": "apps-s-1vcpu-0.5gb",
            "kind": "PRE_DEPLOY",
        }
    ],
    "workers": [
        {
            "name": "api",
            "gitlab": {
                "branch": "main",
                "deploy_on_push": True,
                "repo": "digitalocean/sample-golang",
            },
            "image": {
                "registry": "registry.hub.docker.com",
                "registry_type": "DOCR",
                "repository": "origin/master",
                "tag": "latest",
            },
            "dockerfile_path": "path/to/Dockerfile",
            "build_command": "npm run build",
            "run_command": "bin/api",
            "source_dir": "path/to/dir",
            "envs": [
                {
                    "key": "BASE_URL",
                    "scope": "BUILD_TIME",
                    "type": "GENERAL",
                    "value": "http://example.com",
                }
            ],
            "environment_slug": "node-js",
            "log_destinations": {
                "name": "my_log_destination",
                "papertrail": {
                    "endpoint": "https://mypapertrailendpoint.com"
                },
                "datadog": {
                    "endpoint": "https://mydatadogendpoint.com",
                    "api_key": "abcdefghijklmnopqrstuvwxyz0123456789",
                },
                "logtail": {
                    "token": "abcdefghijklmnopqrstuvwxyz0123456789"
                },
               "open_search": {
                    "endpoint": "https://myopensearchendpoint.com:9300"
                    "index_name": "logs"
                    "basic_auth": {
                        "user": "doadmin",
                        "password": "password"
                    }
                },
            },
            "instance_count": 2,
            "instance_size_slug": "apps-s-1vcpu-0.5gb",
        }
    ],
    "functions": [
        {
            "cors": {
                "allow_origins": [
                    {"exact": "https://www.example.com"},
                    {"regex": "^.*example.com"},
                ],
                "allow_methods": [
                    "GET",
                    "OPTIONS",
                    "POST",
                    "PUT",
                    "PATCH",
                    "DELETE",
                ],
                "allow_headers": ["Content-Type", "X-Custom-Header"],
                "expose_headers": ["Content-Encoding", "X-Custom-Header"],
                "max_age": "5h30m",
                "allow_credentials": False,
            },
            "routes": [{"path": "/api", "preserve_path_prefix": True}],
            "name": "api",
            "source_dir": "path/to/dir",
            "alerts": [
                {
                    "rule": "CPU_UTILIZATION",
                    "disabled": False,
                    "operator": "GREATER_THAN",
                    "value": 2.32,
                    "window": "FIVE_MINUTES",
                }
            ],
            "envs": [
                {
                    "key": "BASE_URL",
                    "scope": "BUILD_TIME",
                    "type": "GENERAL",
                    "value": "http://example.com",
                }
            ],
            "gitlab": {
                "branch": "main",
                "deploy_on_push": True,
                "repo": "digitalocean/sample-golang",
            },
            "log_destinations": {
                "name": "my_log_destination",
                "papertrail": {
                    "endpoint": "https://mypapertrailendpoint.com"
                },
                "datadog": {
                    "endpoint": "https://mydatadogendpoint.com",
                    "api_key": "abcdefghijklmnopqrstuvwxyz0123456789",
                },
                "logtail": {
                    "token": "abcdefghijklmnopqrstuvwxyz0123456789"
                },
               "open_search": {
                    "endpoint": "https://myopensearchendpoint.com:9300"
                    "index_name": "logs"
                    "basic_auth": {
                        "user": "doadmin",
                        "password": "password"
                    }
                },
            },
        }
    ],
    "databases": [
        {
            "cluster_name": "cluster_name",
            "db_name": "my_db",
            "db_user": "superuser",
            "engine": "PG",
            "name": "prod-db",
            "production": True,
            "version": "12",
        }
    ],
    vpc: {
        id: c22d8f48-4bc4-49f5-8ca0-58e7164427ac,
    }
}
update_resp = client.apps.update(id="bb245ba", body=req)

Add a Function to an App Using the Control Panel

Go to the Apps page of the DigitalOcean Control Panel and select your app. Click Add components, then choose Create resources from source code to add a Function.

An App Platform app with the Add components menu selected, and the Create resources from source code option highlighted.

On the Add resources screen:

  • Select your deployment source, either a Git repository or a container image. If you have not previously created an app on App Platform, the repository service may prompt you to provide DigitalOcean with read permissions to your account.
  • If using a Git repository, choose a branch to deploy from. By default, App Platform builds from the repository's root. If your code lives in a subdirectory (for example, in a monorepo), set the source directory to match.
  • Clear the Autodeploy checkbox if you want to stop automatic redeploys when the repository changes.
  • Click Next.
The Create an app screen with the Git repository tab selected, and GitHub selected as the Git provider.

App Platform retrieves your code, analyzes your repository, and automatically selects the appropriate runtime (such as Node or Ruby). If you need to override this behavior, upload a Dockerfile to your branch and restart the creation process.

Configure Resource Settings

The Resource settings table displays the configuration settings, some of which the detection system auto-fills.

The Resource settings table showing a function selected as the Resource type and configuration settings for a function.

You can configure the following settings:

  • Name: A unique name for the component.

  • Branch: The branch to deploy from. You can enable automatic redeploys when changes are made to this branch.

  • HTTP request routes: For web services and static sites only. The URL path where the app can be accessed, such as your-app-v3cl4.ondigitalocean.app/api. If not specified, the app is accessible from the provided hostname's root.

  • Environment variables: Key-value pairs available to your app at runtime that let you keep configuration separate from application code. Use them to provide secrets, API keys, and other external settings, such as connection details for an external database.

Note
For Functions components, you must also add the environment variables to the component’s project.yml configuration file. If you configured a source directory for the component, place the project.yml file in that directory. Otherwise, place it in the repository root.

See the Templating section of the Functions project configuration documentation for examples and more information on configuring App Platform environment variables in project.yml. In addition, see How to Use Environment Variables in App Platform.

Set App-Level Environment Variables

App-level environment variables are available to all components in your app. Use them for shared configuration, secrets, API keys, or other values your app needs at build time or runtime.

To set app-level environment variables:

  • Click Edit in the App-level environment variables section.
  • Click Add environment variable, type a key and value, then select a scope.
  • Select Encrypt to obscure the value in build, deployment, and application logs.

For dynamic, app-specific variables that your app can reference, see Use Bindable Variables.

Review and Deploy

Review the configuration and pricing details in the Summary section, then click Add resources.

App Platform creates the component with the selected settings and deploys it automatically. You can view or update the component's configuration on the Settings page.

Edit Functions

Go to the Apps page, select your app, then click the Settings tab. Select the Function you want to edit.

Click Edit beside a setting you want to change, then click Save.

Get Function URLs

A Functions component can contain multiple individual functions. To find the live URL of each function in a Functions component, click your app, click the Settings tab, and then click the Functions component you want to inspect.

The Settings page showing the Functions table.

The Functions table lists each function deployed within the component. The Name of each function is a clickable link that opens the function’s URL in a new window in your browser.

Note
Opening the live URL of a function directly in your browser can result in errors if your function is expecting input parameters. Use API testing tools like Postman, curl, or your programming language’s HTTP client library to test the URL with properly formatted HTTP requests.

Enable Trusted Sources

Functions in App Platform support trusted sources with DigitalOcean Managed Databases. You can add your app as a trusted source on a managed database cluster to enable a secure connection from the app to the database cluster.

When you add an app as a trusted source for a database, all components of the app, including any functions, have secure access to the database cluster.

Note
When you remove an App Platform app from your database’s trusted sources, the app’s functions remain trusted until the entire app is redeployed. You must redeploy your app to fully remove access.

To configure the functions component to connect to the database cluster, set environment variables and set each value to the bindable variable for your database component (for example, ${db.DATABASE_URL} or ${postgres-db.DATABASE_URL} if your database is named postgres-db), not a literal connection string:

  • DATABASE_URL for the connection URL (for example, ${db.DATABASE_URL}).
  • DATABASE_PASSWORD for the password (for example, ${db.PASSWORD}).
  • DATABASE_USER for the username to use to connect (for example, ${db.USERNAME}).
  • DATABASE_NAME for the name of the database cluster (for example, ${db.DATABASE}).

When using functions to connect to database clusters, reuse the connection across multiple invocations, or close it after each invocation to avoid exceeding the cluster’s connection limit. The function runtime may be reused between invocations, so you can initialize the connection in a persistent global variable.

Trusted sources are not currently supported with MongoDB or Postgres connection pools.

Log Forwarding

Functions components in App Platform can forward console and error logs to a logging provider. You can choose DigitalOcean’s Managed OpenSearch, or the third-party services Logtail and Datadog:

Note
We do not currently support Papertrail as a log forwarding provider for Functions components.

Enabling log forwarding requires two steps:

  1. Configure a log forwarding destination.
  2. Update your function’s project.yml file to handle the LOG_DESTINATIONS environment variable.

Configure a Log Forwarding Destination

You can configure a log forwarding destination using either the Control Panel or by updating your app spec.

Go to the Apps page and select your app. Click the Settings tab, then click the Functions component.

In the Log Forwarding section, click Edit, then choose a log forwarding service, either Managed OpenSearch, Datadog, or Logtail.

  • For Managed OpenSearch, enter a destination name, select a database, then select a user. Optionally update the default index name. Then click Add Log Destination.
The Forward logs to Managed OpenSearch dialog with example values for the fields Destination name, Select a database, User, and Index name.
  • For Datadog, enter a destination name, an endpoint, and an API key. Then click Add Log Destination.

  • For Logtail, create an HTTP source (for example, platform: http). Enter the resulting token and a destination name, then click Add Log Destination.

You can add log forwarding destinations to functions by updating the app spec. See the log_destinations section of the App Spec reference for details. Here is an example Logtail destination:

log_destinations:
- name: <example-destination>
  logtail: 
    token: <your-token>

Place the log forwarding destination in the portion of your app spec that configures the function you’re enabling log forwarding for.

In the same component section, add the following environment variable:

  envs:
  - key: LOG_DESTINATIONS
    scope: RUN_AND_BUILD_TIME
    value: ${_self.FUNCTIONS_LOG_DESTINATION_JSON}

App Platform provides the value of ${_self.FUNCTIONS_LOG_DESTINATION_JSON}, which is a JSON structure with configuration details for log forwarding destinations.  

Note
Adding a log forwarding destination to a Functions component also creates an environment variable with the key LOG_DESTINATIONS. You can view this variable on the Settings page in the Environment Variables section. Removing this environment variable stops log forwarding from working.

Update Your project.yml File

To complete the setup, add the LOG_DESTINATIONS environment variable to your function’s project.yml file:

environment:
  LOG_DESTINATIONS: ${LOG_DESTINATIONS}

This passes the component-level LOG_DESTINATIONS environment variable to the Functions process. After updating project.yml, redeploy your Functions component.

Destroy Functions

Go to the Apps page, select your app, then click the Settings tab. Select the Function you want to destroy.

At the bottom of the page, click Destroy Component. Enter the Function's name to confirm, then click Destroy.

Function Limits

All Functions product limits also apply to Functions components in App Platform. See the following link for details.

Functions Limits

Limits and known issues for DigitalOcean Functions.

We can't find any results for your search.

Try using different keywords or simplifying your search terms.