Back to Blog
Guide8 min read2026-05-01

Serverless Functions: A Complete Developer's Guide

Serverless functions let you ship backend logic without managing servers — this complete guide covers architecture, patterns, and how to get started.

The Serverless Promise

"Serverless" does not mean there are no servers. It means you do not have to think about them. The platform provisions compute, handles scaling, and charges you only for the time your code actually runs. For developers, this is a meaningful shift: you write functions, not infrastructure configurations.

This guide covers how serverless functions work, the patterns that make them powerful, common pitfalls, and how to deploy your first function on PandaStack.

Anatomy of a Serverless Function

A serverless function is a single unit of logic — typically one exported handler — that accepts an input and returns an output. It is stateless: each invocation is independent. Any state that needs to persist must live in a database, cache, or object store.

Here is a well-structured Node.js serverless function:

// processOrder.js
const main = async (params) => {
  const { orderId, userId } = params;

  if (!orderId || !userId) {
    return {
      statusCode: 400,
      body: JSON.stringify({ error: 'orderId and userId are required' })
    };
  }

  // Business logic here
  const result = await processOrder(orderId, userId);

  return {
    statusCode: 200,
    body: JSON.stringify({ success: true, result })
  };
};

module.exports = { main };

And the Python equivalent:

# process_order.py
import json

def main(params):
    order_id = params.get('orderId')
    user_id = params.get('userId')

    if not order_id or not user_id:
        return {
            'statusCode': 400,
            'body': json.dumps({'error': 'orderId and userId are required'})
        }

    # Business logic here
    result = process_order(order_id, user_id)

    return {
        'statusCode': 200,
        'body': json.dumps({'success': True, 'result': result})
    }

Core Serverless Patterns

1. HTTP API Pattern

The simplest and most common pattern. A function handles an HTTP request and returns a response. This replaces a route in an Express or Flask application.

// GET /users/:id
const main = async (params) => {
  const user = await db.users.findById(params.id);
  if (!user) return { statusCode: 404, body: JSON.stringify({ error: 'Not found' }) };
  return { statusCode: 200, body: JSON.stringify(user) };
};

module.exports = { main };

2. Webhook Handler Pattern

Receive an event from a third-party service, validate it, and trigger downstream logic.

const crypto = require('crypto');

const main = (params) => {
  const signature = params.__ow_headers['x-hub-signature-256'];
  const payload = JSON.stringify(params.body);
  const expected = 'sha256=' + crypto
    .createHmac('sha256', process.env.WEBHOOK_SECRET)
    .update(payload)
    .digest('hex');

  if (signature !== expected) {
    return { statusCode: 401, body: JSON.stringify({ error: 'Invalid signature' }) };
  }

  // Process event asynchronously
  return { statusCode: 200, body: JSON.stringify({ received: true }) };
};

module.exports = { main };

3. Data Transformation Pattern

Accept raw input, transform it, and return the processed result. Useful for ETL pipelines and API aggregation.

4. Scheduled Task Pattern

Pair a serverless function with a cron trigger. PandaStack's cronjob system can invoke a function endpoint on any cron schedule — run nightly reports, clean up stale records, or sync data between systems.

The Lifecycle of a Function Invocation

  1. 1Trigger — An HTTP request, schedule, or event fires
  2. 2Dispatch — The platform routes the request to an available worker
  3. 3Cold start (if needed) — A new runtime is initialized if no warm instance exists
  4. 4Execution — Your function code runs
  5. 5Response — The return value is sent back to the caller
  6. 6Teardown — The runtime is recycled or kept warm for subsequent requests

Understanding this lifecycle helps you optimize for latency and cost.

Deployment on PandaStack

PandaStack edge functions run on Apache OpenWhisk, supporting Node.js and Python runtimes. Deploy with the CLI:

npm install -g @pandastack/cli
panda login

# Deploy Node.js function
panda functions deploy ./processOrder.js --name process-order --runtime nodejs

# Deploy Python function
panda functions deploy ./process_order.py --name process-order-py --runtime python

Each function gets an HTTPS endpoint you can call immediately. Monitor invocations and logs at dashboard.pandastack.io.

Best Practices

  • Keep functions small — One function, one responsibility
  • Validate inputs early — Return 400 before doing any expensive work
  • Use environment variables for secrets — Never hardcode credentials
  • Handle errors explicitly — Always return a meaningful status code
  • Log structured JSON — Makes filtering and alerting much easier

Conclusion

Serverless functions are not a silver bullet, but for HTTP-driven workloads, webhooks, and lightweight APIs, they dramatically reduce the operational burden on development teams. Write the logic, deploy it, and let the platform manage the rest. Start at dashboard.pandastack.io and ship your first function today.

Ready to deploy?

Start free on PandaStack — no credit card required.

Start free on PandaStack

More in Guide

Browse all Guide articles →

See also