Trigger Details
EdgeBase functions can be triggered in four ways — each suited to different use cases:
| Trigger | When it fires | Example |
|---|---|---|
| HTTP | Client calls a URL | GET /api/functions/orders/:id |
| DB | A table record is inserted, updated, or deleted | Log analytics on new order |
| Auth | A user signs up, signs in, resets password, etc. | Create a profile on signup |
| Schedule | Cron schedule fires | Clean up expired sessions hourly |
This page shows practical patterns for each trigger type. For the full context API (admin.db(), admin.auth, etc.), see Context API.
For an introduction to DB triggers with practical examples, see Database Triggers.
DB Trigger — Cross-Table Access
A DB trigger's handler receives the triggering record via data. To write to a different table, use admin.db().table():
export default defineFunction({
trigger: { type: 'db', table: 'orders', event: 'insert' },
handler: async ({ data, admin }) => {
await admin.db('shared').table('analytics').insert({
type: 'new_order',
orderId: data.after.id,
});
},
});
Cross-DO Access
Access any table from any function; EdgeBase handles Cross-DO routing automatically:
handler: async ({ admin }) => {
// Same-group = local JOIN (fast)
const users = await admin.db('shared').table('users').list();
// Different DO = Cross-DO fetch (automatic, transparent)
const posts = await admin.db('shared').table('posts').list();
};
Auth Hook Context
Auth hooks run in the auth handler context. Use context.admin.db().table() for database access:
export default defineFunction({
trigger: { type: 'auth', event: 'afterSignUp' },
handler: async ({ data, admin }) => {
await admin
.db('shared')
.table('profiles')
.insert({
userId: data.userId,
displayName: data.displayName || 'New User',
});
await admin.auth.setCustomClaims(data.userId, { plan: 'free' });
},
});
Schedule — Without DB Scope
Scheduled functions can access any DB block via context.admin.db(namespace).table():
export default defineFunction({
trigger: { type: 'schedule', cron: '0 * * * *' },
handler: async ({ admin }) => {
const deleted = await admin.sql(
'shared',
undefined,
'DELETE FROM sessions WHERE expiresAt < ? RETURNING id',
[new Date().toISOString()],
);
console.log('Deleted stale sessions:', deleted.length);
},
});
Schedule trigger ownership is config-driven at deploy time:
- App Function schedule triggers contribute their cron expressions to the managed deploy cron set.
cloudflare.extraCronscan add additionalscheduled()wake-ups, but those cron entries are not attached to a specific schedule function.- If you add
cloudflare.extraCrons, your Worker runtime must decide what to do whenscheduled()fires at those times.
HTTP Trigger — File-System Routing
HTTP functions use file-system routing by default. The file path determines the URL, and named exports (GET, POST, PUT, PATCH, DELETE) determine the HTTP method:
// functions/orders/[orderId].ts -> /api/functions/orders/:orderId
import { defineFunction, FunctionError } from '@edgebase/shared';
export const GET = defineFunction(async ({ params, admin, auth }) => {
if (!auth) throw new FunctionError('unauthenticated', 'Login required');
const order = await admin.db('shared').table('orders').get(params.orderId);
if (!order) throw new FunctionError('not-found', 'Order not found');
return Response.json(order);
});
export const DELETE = defineFunction(async ({ params, admin, auth }) => {
if (!auth) throw new FunctionError('unauthenticated', 'Login required');
await admin.db('shared').table('orders').delete(params.orderId);
return Response.json({ deleted: true });
});
Dynamic route parameters ([param] segments) are available via context.params. See Context API for details.
You can define multiple HTTP methods in the same file. Each named export becomes a separate handler. Use index.ts for collection endpoints (e.g., functions/orders/index.ts for /api/functions/orders).
If you need a cleaner public route, use trigger.path on a default export:
export default defineFunction({
trigger: { type: 'http', method: 'GET', path: '/analytics/orders' },
handler: async ({ admin }) => {
const { items } = await admin.db('shared').table('orders').list();
return { items };
},
});
That function is served at GET /api/functions/analytics/orders.
Function Bundling
Functions in functions/ are automatically discovered and bundled during npx edgebase deploy. The CLI generates a lazy-import registry that loads each function on demand.