Skip to main content

Trigger Details

EdgeBase functions can be triggered in four ways — each suited to different use cases:

TriggerWhen it firesExample
HTTPClient calls a URLGET /api/functions/orders/:id
DBA table record is inserted, updated, or deletedLog analytics on new order
AuthA user signs up, signs in, resets password, etc.Create a profile on signup
ScheduleCron schedule firesClean 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.

Getting Started with DB Triggers

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.extraCrons can add additional scheduled() 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 when scheduled() 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.

tip

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.