Skip to content

DigitalOcean Functions Overview

Introduction

DigitalOcean Functions is a serverless computing platform that lets you run code without managing servers. Deploy functions that automatically scale, pay only for execution time, and integrate seamlessly with other DigitalOcean services.

Key Features

  • Serverless: No infrastructure management
  • Auto-Scaling: Scales automatically with demand
  • Pay-per-Use: Billed per execution
  • Multiple Languages: Node.js, Python, Go, PHP
  • Event-Driven: Trigger from HTTP, schedules, events
  • Fast Cold Starts: Optimized performance
  • Built-in Monitoring: Logs and metrics included
  • CI/CD Integration: Deploy from Git
  • Environment Variables: Secure configuration
  • Package Support: Use npm, pip, go modules

Functions Architecture

┌─────────────────────────────────────────────────────────────┐
│                    Triggers                                  │
│  ├─> HTTP Requests                                          │
│  ├─> Scheduled (Cron)                                       │
│  ├─> Webhooks                                               │
│  └─> Events                                                 │
└────────────────────────────┬────────────────────────────────┘
                    ┌────────▼────────┐
                    │  API Gateway    │
                    │  (Routing)      │
                    └────────┬────────┘
        ┌────────────────────┼────────────────────┐
        │                    │                    │
   ┌────▼────┐         ┌────▼────┐         ┌────▼────┐
   │Function │         │Function │         │Function │
   │Instance │         │Instance │         │Instance │
   │   #1    │         │   #2    │         │   #3    │
   └────┬────┘         └────┬────┘         └────┬────┘
        │                    │                    │
        └────────────────────┼────────────────────┘
                    ┌────────▼────────┐
                    │   Resources     │
                    │  (DB, Storage)  │
                    └─────────────────┘

Auto-scaling: 0 to 1000+ instances based on load

Supported Runtimes

Node.js

Versions:
├─> Node.js 18.x (LTS)
├─> Node.js 20.x (Latest)
└─> npm packages supported

Use Cases:
├─> API endpoints
├─> Webhooks
├─> Data processing
└─> Integrations

Python

Versions:
├─> Python 3.9
├─> Python 3.10
├─> Python 3.11
└─> pip packages supported

Use Cases:
├─> Data analysis
├─> ML inference
├─> Automation
└─> Scraping

Go

Versions:
├─> Go 1.19
├─> Go 1.20
├─> Go 1.21
└─> Go modules supported

Use Cases:
├─> High-performance APIs
├─> Concurrent processing
├─> System utilities
└─> Microservices

PHP

Versions:
├─> PHP 8.1
├─> PHP 8.2
└─> Composer packages supported

Use Cases:
├─> Web hooks
├─> Form processing
├─> Legacy integrations
└─> CMS extensions

Use Cases

1. API Endpoints

REST APIs:
├─> CRUD operations
├─> Data validation
├─> Authentication
└─> Rate limiting

Example:
├─> GET /api/users
├─> POST /api/users
├─> PUT /api/users/:id
└─> DELETE /api/users/:id

2. Webhooks

Event Handlers:
├─> GitHub webhooks
├─> Stripe payments
├─> Slack commands
└─> Custom integrations

Example:
├─> Process payment events
├─> Deploy on push
├─> Send notifications
└─> Update databases

3. Scheduled Tasks

Cron Jobs:
├─> Data backups
├─> Report generation
├─> Cleanup tasks
└─> Monitoring checks

Example:
├─> Daily database backup
├─> Hourly health checks
├─> Weekly reports
└─> Monthly cleanup

4. Data Processing

ETL Pipelines:
├─> Image processing
├─> File conversion
├─> Data transformation
└─> Batch processing

Example:
├─> Resize uploaded images
├─> Convert video formats
├─> Parse CSV files
└─> Generate thumbnails

5. Integrations

Third-Party Services:
├─> Payment processing
├─> Email sending
├─> SMS notifications
└─> Social media posting

Example:
├─> Stripe payment handler
├─> SendGrid email sender
├─> Twilio SMS sender
└─> Twitter bot

Pricing

Free Tier

Included:
├─> 90,000 GB-seconds/month
├─> 90,000 requests/month
└─> No credit card required

Equivalent to:
├─> ~25 hours of 1GB function
└─> ~90,000 quick requests
Compute:
├─> $0.0000185 per GB-second
└─> Billed per 100ms

Requests:
├─> $0.30 per million requests
└─> First 90k free

Example Cost:
├─> 1M requests: $0.27
├─> 1M GB-seconds: $18.50
└─> Typical API: $5-20/month

Function Structure

Basic Function (Node.js)

// packages/hello/hello.js
function main(args) {
  const name = args.name || 'World';
  return {
    body: {
      message: `Hello, ${name}!`
    }
  };
}

exports.main = main;

With Dependencies

// packages/api/package.json
{
  "name": "api",
  "version": "1.0.0",
  "dependencies": {
    "axios": "^1.6.0"
  }
}

// packages/api/api.js
const axios = require('axios');

async function main(args) {
  const response = await axios.get('https://api.example.com/data');
  return {
    body: response.data
  };
}

exports.main = main;

Python Function

# packages/process/process.py
import json

def main(args):
    data = args.get('data', [])
    processed = [item * 2 for item in data]

    return {
        'body': {
            'result': processed
        }
    }

Go Function

// packages/handler/handler.go
package main

import (
    "encoding/json"
)

type Response struct {
    Body map[string]interface{} `json:"body"`
}

func Main(args map[string]interface{}) Response {
    name := "World"
    if n, ok := args["name"].(string); ok {
        name = n
    }

    return Response{
        Body: map[string]interface{}{
            "message": "Hello, " + name + "!",
        },
    }
}

Project Configuration

project.yml

packages:
  - name: api
    functions:
      - name: users
        runtime: nodejs:18
        web: true
        environment:
          DATABASE_URL: ${DATABASE_URL}
        limits:
          timeout: 30000
          memory: 256

      - name: process
        runtime: python:3.11
        web: false
        schedule: '0 * * * *'  # Hourly
        limits:
          timeout: 60000
          memory: 512

Deployment

Using doctl

# Install doctl
brew install doctl

# Authenticate
doctl auth init

# Connect to Functions
doctl serverless connect

# Deploy
doctl serverless deploy .

# List functions
doctl serverless functions list

# Invoke function
doctl serverless functions invoke api/users

# View logs
doctl serverless activations logs --function api/users

Using GitHub Actions

# .github/workflows/deploy.yml
name: Deploy Functions

on:
  push:
    branches: [main]

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3

      - name: Install doctl
        uses: digitalocean/action-doctl@v2
        with:
          token: ${{ secrets.DIGITALOCEAN_TOKEN }}

      - name: Deploy Functions
        run: |
          doctl serverless connect
          doctl serverless deploy .

Best Practices

1. Performance

Optimization:
├─> Keep functions small and focused
├─> Minimize cold start time
├─> Use connection pooling
├─> Cache external data
└─> Optimize dependencies

Tips:
├─> Reuse connections
├─> Lazy load modules
├─> Use async/await
└─> Implement timeouts

2. Security

Best Practices:
├─> Use environment variables for secrets
├─> Validate input data
├─> Implement rate limiting
├─> Use HTTPS only
└─> Follow least privilege

Example:
├─> Store API keys in env vars
├─> Validate request parameters
├─> Limit request size
└─> Use authentication

3. Error Handling

async function main(args) {
  try {
    // Validate input
    if (!args.email) {
      return {
        statusCode: 400,
        body: { error: 'Email required' }
      };
    }

    // Process request
    const result = await processEmail(args.email);

    return {
      statusCode: 200,
      body: { success: true, result }
    };
  } catch (error) {
    console.error('Error:', error);
    return {
      statusCode: 500,
      body: { error: 'Internal server error' }
    };
  }
}

4. Monitoring

Track Metrics:
├─> Execution time
├─> Error rate
├─> Invocation count
├─> Memory usage
└─> Cold starts

Tools:
├─> Built-in logs
├─> Activation history
├─> Custom metrics
└─> External monitoring

Common Patterns

REST API

// packages/api/users.js
const users = [];

function main(args) {
  const method = args.__ow_method;
  const path = args.__ow_path;

  switch (method) {
    case 'GET':
      return { body: users };

    case 'POST':
      const user = JSON.parse(args.__ow_body);
      users.push(user);
      return { statusCode: 201, body: user };

    case 'DELETE':
      const id = path.split('/').pop();
      const index = users.findIndex(u => u.id === id);
      if (index > -1) {
        users.splice(index, 1);
        return { statusCode: 204 };
      }
      return { statusCode: 404 };

    default:
      return { statusCode: 405 };
  }
}

Webhook Handler

// packages/webhooks/github.js
const crypto = require('crypto');

function verifySignature(payload, signature, secret) {
  const hmac = crypto.createHmac('sha256', secret);
  const digest = 'sha256=' + hmac.update(payload).digest('hex');
  return crypto.timingSafeEqual(
    Buffer.from(signature),
    Buffer.from(digest)
  );
}

async function main(args) {
  const signature = args.__ow_headers['x-hub-signature-256'];
  const payload = args.__ow_body;

  if (!verifySignature(payload, signature, process.env.GITHUB_SECRET)) {
    return { statusCode: 401, body: { error: 'Invalid signature' } };
  }

  const event = JSON.parse(payload);

  // Process webhook event
  console.log('Received event:', event.action);

  return { statusCode: 200, body: { success: true } };
}

Scheduled Task

# packages/tasks/backup.py
import os
from datetime import datetime

def main(args):
    # Perform backup
    timestamp = datetime.now().isoformat()

    # Your backup logic here
    print(f"Backup started at {timestamp}")

    # Upload to Spaces
    # ...

    return {
        'body': {
            'success': True,
            'timestamp': timestamp
        }
    }

Troubleshooting

Function Not Responding

# Check function status
doctl serverless functions list

# View recent activations
doctl serverless activations list --function api/users

# Get activation details
doctl serverless activations get ACTIVATION_ID

# View logs
doctl serverless activations logs --function api/users

Timeout Issues

# Increase timeout in project.yml
functions:
  - name: slow-function
    limits:
      timeout: 60000  # 60 seconds
      memory: 512     # More memory

Cold Start Optimization

// Initialize outside handler
const db = require('./db');
let connection;

async function main(args) {
  // Reuse connection
  if (!connection) {
    connection = await db.connect();
  }

  // Use connection
  const result = await connection.query('SELECT * FROM users');

  return { body: result };
}

Documentation Structure

  1. Functions Overview - This page
  2. Creating Functions - Development guide
  3. Deploying Functions - Deployment methods
  4. Function Patterns - Common use cases

Next Steps