Beyond Hello World
Edge functions are easy to introduce with a "Hello World" example. But what do they actually solve in production? This guide covers ten real use cases that developers reach for edge functions to handle — with code examples you can adapt and deploy on PandaStack today.
PandaStack edge functions run on Apache OpenWhisk and support Node.js and Python runtimes, invoked via HTTP.
---
1. Webhook Receivers
Receive events from Stripe, GitHub, Slack, or any third-party service, validate them, and trigger downstream work.
// stripeWebhook.js
const crypto = require('crypto');
const main = (params) => {
const signature = params.__ow_headers['stripe-signature'];
const payload = JSON.stringify(params.body);
const expected = crypto
.createHmac('sha256', process.env.STRIPE_WEBHOOK_SECRET)
.update(payload).digest('hex');
if (!signature.includes(expected)) {
return { statusCode: 401, body: JSON.stringify({ error: 'Invalid signature' }) };
}
const event = params.body;
// Handle event.type: 'payment_intent.succeeded', etc.
return { statusCode: 200, body: JSON.stringify({ received: true }) };
};
module.exports = { main };---
2. Form Submission Handlers
Process contact forms, newsletter signups, or support requests without a backend server.
// contactForm.js
const main = async (params) => {
const { name, email, message } = params;
if (!name || !email || !message) {
return { statusCode: 400, body: JSON.stringify({ error: 'All fields required' }) };
}
await sendEmailViaMailgun({ to: process.env.SUPPORT_EMAIL, name, email, message });
return { statusCode: 200, body: JSON.stringify({ sent: true }) };
};
module.exports = { main };---
3. JWT Token Validation
Validate authentication tokens before proxying requests to protected services.
// validateToken.js
const jwt = require('jsonwebtoken');
const main = (params) => {
const token = (params.__ow_headers?.authorization || '').replace('Bearer ', '');
try {
const payload = jwt.verify(token, process.env.JWT_SECRET);
return { statusCode: 200, body: JSON.stringify({ valid: true, userId: payload.sub }) };
} catch {
return { statusCode: 401, body: JSON.stringify({ valid: false }) };
}
};
module.exports = { main };---
4. Data Transformation and Normalization
Transform messy third-party API responses into clean, consistent shapes your frontend can consume.
# normalize_product.py
import json
import requests
def main(params):
product_id = params.get('productId')
raw = requests.get(f"https://legacy-api.example.com/products/{product_id}").json()
normalized = {
'id': raw.get('prod_id'),
'name': raw.get('productName'),
'price': float(raw.get('unit_price', 0)),
'inStock': raw.get('stock_qty', 0) > 0
}
return {'statusCode': 200, 'body': json.dumps({'product': normalized})}---
5. URL Shortener Backend
Generate and resolve short URLs, storing mappings in a database.
// shortener.js
const crypto = require('crypto');
const main = async (params) => {
const { action, url, code } = params;
if (action === 'create') {
const shortCode = crypto.randomBytes(4).toString('hex');
await db.save(shortCode, url);
return { statusCode: 200, body: JSON.stringify({ shortCode, url: `https://pnda.link/${shortCode}` }) };
}
if (action === 'resolve') {
const target = await db.get(code);
if (!target) return { statusCode: 404, body: JSON.stringify({ error: 'Not found' }) };
return { statusCode: 200, body: JSON.stringify({ target }) };
}
return { statusCode: 400, body: JSON.stringify({ error: 'Invalid action' }) };
};
module.exports = { main };---
6. Feature Flag Evaluation
Evaluate feature flags server-side and return the active set for a user — without exposing your flag configuration to the client.
// featureFlags.js
const FLAGS = JSON.parse(process.env.FEATURE_FLAGS || '{}');
const main = (params) => {
const { userId, plan } = params;
const active = Object.entries(FLAGS)
.filter(([, rule]) => {
if (rule.plans && !rule.plans.includes(plan)) return false;
if (rule.rollout) return (parseInt(userId) % 100) < rule.rollout;
return rule.enabled;
})
.map(([name]) => name);
return { statusCode: 200, body: JSON.stringify({ flags: active }) };
};
module.exports = { main };---
7. Slack / Discord Notifier
Send notifications to Slack or Discord channels from any trigger — deployments, alerts, or cronjob completions.
# notify_slack.py
import json
import urllib.request
def main(params):
webhook_url = params.get('webhookUrl') or __import__('os').environ.get('SLACK_WEBHOOK')
message = params.get('message', 'Notification from PandaStack')
payload = json.dumps({'text': message}).encode()
req = urllib.request.Request(webhook_url, data=payload,
headers={'Content-Type': 'application/json'})
urllib.request.urlopen(req)
return {'statusCode': 200, 'body': json.dumps({'notified': True})}---
8. A/B Test Assignment
Deterministically assign users to experiment variants without client-side exposure.
// abAssign.js
const main = (params) => {
const { userId, experiment } = params;
if (!userId || !experiment) {
return { statusCode: 400, body: JSON.stringify({ error: 'userId and experiment required' }) };
}
// Stable hash → consistent assignment per user
const hash = userId.split('').reduce((acc, c) => acc + c.charCodeAt(0), 0);
const variant = hash % 2 === 0 ? 'control' : 'treatment';
return { statusCode: 200, body: JSON.stringify({ userId, experiment, variant }) };
};
module.exports = { main };---
9. Health Check Aggregator
Ping multiple internal services and return a unified health status — useful for monitoring dashboards and uptime checks.
// healthCheck.js
const https = require('https');
const ping = (url) => new Promise((resolve) => {
const start = Date.now();
https.get(url, (res) => {
resolve({ url, status: res.statusCode, latencyMs: Date.now() - start });
}).on('error', () => resolve({ url, status: 0, latencyMs: -1 }));
});
const main = async () => {
const services = (process.env.SERVICES || '').split(',').filter(Boolean);
const results = await Promise.all(services.map(ping));
const healthy = results.every(r => r.status >= 200 && r.status < 300);
return {
statusCode: healthy ? 200 : 503,
body: JSON.stringify({ healthy, services: results })
};
};
module.exports = { main };---
10. Scheduled Report Generator
Pair a PandaStack cronjob with an edge function to generate and email weekly usage reports.
# weekly_report.py
import json
from datetime import datetime, timedelta
def main(params):
end_date = datetime.utcnow()
start_date = end_date - timedelta(days=7)
# Query your database for the reporting period
metrics = query_metrics(start_date.isoformat(), end_date.isoformat())
report = {
'period': f"{start_date.date()} to {end_date.date()}",
'totalRequests': metrics['total'],
'p99LatencyMs': metrics['p99'],
'errorRate': metrics['error_rate']
}
send_report_email(report)
return {'statusCode': 200, 'body': json.dumps({'generated': True, 'report': report})}Schedule it with PandaStack cronjobs to run every Monday at 9am.
---
Deploying Any of These on PandaStack
npm install -g @pandastack/cli
panda login
# Deploy any function above
panda functions deploy ./stripeWebhook.js --name stripe-webhook --runtime nodejs
panda functions deploy ./weekly_report.py --name weekly-report --runtime pythonManage all your functions, view logs, and monitor usage at dashboard.pandastack.io. Full runtime documentation at docs.pandastack.io.
Conclusion
Edge functions solve real problems across every stage of a production application — from authentication to analytics to notifications. Pick one use case from this list, deploy it in the next 15 minutes, and see how much simpler serverless makes your stack.