Deploy an App on DigitalOcean App Platform

Khimananda Oli 8 min read Database
Deploy an App on DigitalOcean App Platform

By Khimananda Oli | Last reviewed: August 2026

You want to ship code without managing Kubernetes clusters or patching Linux servers, but you still need production-grade reliability. When you deploy an app on DigitalOcean App Platform, you trade low-level infrastructure control for a fully managed PaaS that handles builds, scaling, TLS, and routing automatically. This guide walks you through the exact configuration, security practices, and operational checks I use to run client workloads reliably in 2026.

Git RepositorySource CodeApp PlatformBuild & DeployAuto-ScalingTLS TerminationManaged DBPostgreSQL / MySQLGlobal CDNEdge CachingEnd UsersHTTPS Traffic
High-level architecture when you deploy an app on DigitalOcean App Platform: source code triggers automated builds, traffic flows through TLS-terminated CDN to auto-scaled containers with managed database backends.

How do you deploy an app on DigitalOcean App Platform using a spec file?

The most reliable way to deploy an app on DigitalOcean App Platform is declaratively via a YAML spec file rather than clicking through the dashboard UI. Dashboard configurations drift over time and cannot be peer-reviewed. A spec file lives in your repository, gets versioned with your code, and can be applied repeatedly via CLI or CI pipeline. For teams managing multiple environments, this approach aligns with the principles discussed in our infrastructure as code practical guide.

Create the app spec YAML

Save this as .do/app.yaml in your project root. This example deploys a Node.js web service alongside a worker process and a managed PostgreSQL database:

name: my-production-app
region: nyc
services:
- name: web
  github:
    repo: owner/my-app
    branch: main
    deploy_on_push: true
  source_dir: /
  run_command: npm start
  instance_size_slug: professional-xs
  instance_count: 2
  http_port: 8080
  health_check:
    http_path: /healthz
    initial_delay_seconds: 10
    period_seconds: 15
  envs:
  - key: DATABASE_URL
    scope: RUN_TIME
    value: ${db.DATABASE_URL}
  - key: NODE_ENV
    scope: RUN_TIME
    value: production
- name: worker
  github:
    repo: owner/my-app
    branch: main
    deploy_on_push: true
  source_dir: /
  run_command: npm run worker
  instance_size_slug: professional-xs
  instance_count: 1
  envs:
  - key: DATABASE_URL
    scope: RUN_TIME
    value: ${db.DATABASE_URL}
databases:
- name: db
  engine: PG
  version: "16"
  size: db-s-dev-database
  num_nodes: 1
domains:
- domain: app.example.com
  type: PRIMARY

Apply the spec with doctl

Install the DigitalOcean CLI and authenticate. Then create or update your app:

# Create a new app from spec
doctl apps create --spec .do/app.yaml

# Update an existing app after spec changes
doctl apps update <app-id> --spec .do/app.yaml

# Verify deployment status
doctl apps get <app-id> --format ID,Name,Status,CreatedAt

The ${db.DATABASE_URL} reference is critical. It injects the managed database connection string at runtime without ever committing credentials to your repository. DigitalOcean resolves these references automatically during deployment.

What are the common mistakes when configuring environment variables and secrets?

Environment variable misconfiguration causes more failed deployments on App Platform than any other issue. In practice, I see three recurring problems that break production apps.

  • Committing secrets to Git: Never put API keys, database passwords, or tokens directly in your spec file. Use DigitalOcean's encrypted environment variables via the dashboard or doctl apps env set for sensitive values, and reference them in your spec with the scope: RUN_TIME directive.
  • Confusing BUILD_TIME and RUN_TIME scopes: Variables scoped to BUILD_TIME are only available during the build phase (e.g., compilation flags). Variables scoped to RUN_TIME are injected into the running container. Most application configuration needs RUN_TIME. Using the wrong scope means your app starts but cannot connect to dependencies.
  • Missing health check endpoints: Without a defined health_check, App Platform uses TCP connectivity as the only signal. Your container might be running but deadlocked. Always define an HTTP health endpoint that verifies downstream dependencies. If you are building observability into your stack, align this with the patterns in our four golden signals of monitoring article.

For secrets that rotate frequently, consider integrating HashiCorp Vault or AWS Secrets Manager via sidecar or init container patterns, though App Platform's native encrypted env vars suffice for most small-to-medium workloads.

app.yaml Spec${db.DATABASE_URL}scope: RUN_TIMEApp Platform EngineResolves ReferencesInjects Encrypted VarsBuilds Container ImageEncrypted SecretsStored SeparatelyNever in GitRunning ContainerDATABASE_URL=postgres://...NODE_ENV=productionHealth CheckGET /healthz → 200 OK
Secure environment variable flow: spec references are resolved at deploy time, encrypted secrets are injected separately, and health checks validate runtime readiness before serving traffic.

How does DigitalOcean App Platform compare to AWS ECS and Heroku in 2026?

Choosing where to deploy an app on DigitalOcean App Platform versus alternatives depends on your team size, compliance requirements, and tolerance for operational overhead. The following comparison reflects real-world trade-offs I evaluate for clients in Nepal and globally.

CriteriaDigitalOcean App PlatformAWS ECS (Fargate)Heroku
Setup ComplexityLow — YAML spec or UI wizardMedium — requires VPC, IAM, ALB, ECR setupVery Low — git push or CLI
Pricing PredictabilityHigh — flat per-instance monthly ratesVariable — vCPU/memory seconds + data transferLow — dyno costs escalate quickly at scale
Managed Database IntegrationNative — one-click attach, auto-injected credsSeparate RDS provisioning, manual secret managementAdd-ons marketplace, separate billing
Autoscaling GranularityCPU/memory thresholds, min/max instancesFull HPA-style metrics, custom CloudWatch alarmsManual or performance-based, less configurable
Compliance ReadinessSOC 2 Type II, GDPR; limited audit toolingSOC 1/2/3, ISO 27001, HIPAA, FedRAMPSOC 2, ISO 27001; enterprise add-ons required
Best ForSMBs, startups, MVPs, predictable budgetsEnterprise, regulated industries, complex architecturesRapid prototyping, solo developers, legacy apps

If your primary constraint is budget predictability and you do not require HIPAA or FedRAMP, DigitalOcean offers the best balance. For teams already invested in AWS ecosystems or requiring advanced networking (VPC peering, PrivateLink), ECS remains superior despite higher cognitive load. Teams evaluating cloud providers broadly should also review our AWS vs Azure vs Google Cloud comparison for broader context.

How do you monitor and troubleshoot apps after deployment?

Deploying is only half the job. Production operations demand visibility. App Platform provides built-in log aggregation and basic metrics, but serious troubleshooting requires structured approaches.

Access logs and metrics programmatically

# Stream live logs for a specific component
doctl apps logs <app-id> --component web --follow

# Retrieve historical logs with timestamp filtering
doctl apps logs <app-id> --component worker --since 2h

# List all deployments and their statuses
doctl apps list-deployments <app-id> --format ID,Cause,Status,CreatedAt

Implement proper observability

Built-in logs are necessary but insufficient. Instrument your application with OpenTelemetry before going live. Export traces to Jaeger or Tempo, metrics to Prometheus, and logs to Loki or Graylog. This gives you correlation across signals when debugging latency spikes or error bursts. Refer to our OpenTelemetry instrumentation guide for language-specific implementation details.

Set up alerts on error rate and p95 latency, not just uptime. A returning 200 status code with 3-second response times is technically "up" but functionally broken for users. Define SLOs early — even simple ones like "99% of requests under 500ms" — and track error budgets weekly.

App PlatformWeb + Worker ServicesMetricsPrometheus / GrafanaCPU, Memory, HTTP CodesTracesJaeger / TempoRequest Latency, ErrorsLogsLoki / GraylogStructured JSON OutputAlerting & DashboardsSLO Tracking · Error Budgets · On-Call Routing
Recommended observability stack for App Platform: export metrics, traces, and logs to dedicated backends for correlated debugging and proactive alerting beyond built-in capabilities.

When should you avoid DigitalOcean App Platform entirely?

App Platform is excellent within its design boundaries, but it is not universal. Avoid it if you require:

  • Custom kernel modules or eBPF programs: You cannot modify the host kernel. Workloads needing Cilium, custom iptables rules, or specialized networking must use Droplets or Kubernetes.
  • Persistent local storage: Containers are ephemeral. Any file written to disk disappears on redeployment. Use Spaces (S3-compatible object storage) or managed databases for stateful data.
  • Long-running background processes exceeding 24 hours: Workers are designed for bounded tasks. Infinite loops or daemon processes should run on dedicated Droplets or use a job queue with external workers.
  • Multi-region active-active replication: App Platform supports single-region deployment. Global distribution requires separate app instances per region with external data synchronization logic.

Recognizing these limits early prevents costly re-architecture later. If your workload outgrows App Platform, migration to DigitalOcean Kubernetes or ECS is straightforward because your container images and spec definitions remain portable.

Next Steps for Production Deployment

When you deploy an app on DigitalOcean App Platform, treat the initial setup as a foundation, not a destination. Version your spec files, automate deployments through CI, instrument observability before launch, and define SLOs within the first sprint. These practices separate hobby projects from production systems that survive traffic spikes and pass compliance audits. If you need help architecting a production-ready deployment strategy tailored to your team's constraints, get in touch to discuss your specific requirements.

Frequently Asked Questions

Connect your GitHub repository in the App Platform dashboard, select the branch, and configure the build command. DigitalOcean automatically detects frameworks like Laravel or Node.js and deploys updates on every push to the selected branch.

Static sites are free. Basic dynamic services start at five dollars monthly for 512MB RAM and one vCPU. Production plans with dedicated CPU and autoscaling begin around twelve dollars per service component in 2026.

Yes. It auto-detects Laravel via composer.json. Set the PHP version in .php-version file and define artisan migrate in the run command. Use managed databases for MySQL or PostgreSQL instead of local SQLite for production persistence.

Yes. Add your domain in the app settings, then create a CNAME record pointing to your app’s default URL. DigitalOcean provisions automatic TLS certificates via Let’s Encrypt within minutes of DNS propagation completing successfully.

App Platform offers lower base pricing and predictable billing without sleep issues. Heroku provides more add-ons but costs significantly more at scale. Both support PHP, but DigitalOcean integrates better with managed databases and VPCs in 2026.

Check build logs for missing dependencies or incorrect build commands. Ensure your Procfile or app spec matches your framework. Common failures include missing environment variables, incompatible PHP versions, or database connection strings not set in the config panel.

Navigate to your app’s Settings tab, click Environment Variables, and add key-value pairs. Mark sensitive values as encrypted. Variables inject at runtime; redeploy after changes. Never commit secrets to source control or hardcode them in application files.

Yes. Professional plans allow configuring min and max instance counts based on CPU or memory thresholds. Autoscaling adjusts instances automatically during traffic spikes. Basic plans run single instances only and require manual upgrades for scaling capability.

Yes. Add a worker component using the same source repo. Define your queue command like php artisan queue:work in the run configuration. Workers share environment variables with web services but operate independently without HTTP routing or health checks.

Create a Managed Database in DigitalOcean, then add it as a component in your app spec. Connection credentials auto-inject as environment variables. This keeps traffic on private VPC networks, reduces latency, and avoids exposing database ports publicly.

No. App Platform is fully managed and ephemeral. Debug via console commands in the dashboard or stream live logs. For persistent shell access, use a Droplet instead. Design apps to be stateless and observable through logging and metrics.

Enable Preview Deployments in app settings. Each pull request triggers an isolated deployment with a unique URL. Previews auto-delete when merged or closed. This requires GitHub integration and works best with feature-branch workflows and automated testing pipelines.

It uses Heroku-compatible Cloud Native Buildpacks. The PHP buildpack reads composer.json and .php-version files. Customize via app.yaml if auto-detection fails. You can override build and run commands explicitly when standard conventions do not match your project structure.

Built-in metrics show CPU, memory, and HTTP response times. Integrate Datadog or Sentry via environment variables for deeper tracing. Enable log forwarding to Papertrail or OpenSearch. Set alerts on error rates or latency thresholds to catch regressions early.

Yes. Specify a Dockerfile path in your app spec or point to a container registry image. DigitalOcean builds and runs OCI-compliant containers directly. This bypasses buildpack detection and gives full control over runtime environment, dependencies, and system packages.