Plexivo Functions
Run your own TypeScript next to your database, called over HTTPS, on a schedule, when rows change or when a user signs up.
Plexivo Functions run your own server-side code beside your Plexivo Postgres: taking payments, sending emails, calling other APIs, and anything else that needs a secret. Each function knows who called it and can query your database as them, so row-level security still applies.
Set up the runtime#
Functions run in a Plexivo App Runner service of your own, isolated and asleep when idle, and billed as that service. You set it up once per database:
- Turn on the Data API on the Connect tab. Functions use the same project endpoint and keys.
- Open the Functions tab and copy the Plexivo Functions image shown under Set up the runtime.
- Create a public Plexivo App Runner service from that image, on port 8000. Plexivo gives it its HTTPS address and certificate.
- Choose it as the Service and choose Connect runtime.
Write a function#
Choose New function, give it a Name such as send-receipt, write it, and choose Deploy. A function is a module whose default export takes the request and a context:
export default async (req: Request, ctx) => {
const { orderId } = await req.json();
// As the caller: row-level security applies
const { data: order } = await ctx.plexivo.from('orders')
.select('id, total').eq('id', orderId).single();
await fetch('https://api.example.com/receipts', {
method: 'POST',
headers: { authorization: `Bearer ${ctx.env.RECEIPTS_API_KEY}` },
body: JSON.stringify({ email: ctx.user?.email, total: order.total })
});
ctx.log.info('receipt sent for', orderId);
return { sent: true };
};In ctx | What it is |
|---|---|
user, role | The caller’s verified claims, or null for a visitor; anon, authenticated or service_role |
plexivo | A Plexivo JavaScript client acting as the caller: from, select, eq, insert, update, rpc |
admin | A Plexivo client with the service role, past row-level security |
env | The function’s secrets |
log | info, warn, error and debug, kept with each run |
trigger, event | What started the run, and the row or user for an event |
Return a Response, or any value to send it as JSON. Each deploy is a new version; Versions lets you Roll back to this any earlier one.
Call a function#
const { data } = await db.functions.invoke('send-receipt', { body: { orderId } });final res = await db.functions.invoke('send-receipt', body: {'orderId': orderId});
print(res.data);Over HTTPS, a function is at your Project URL followed by /functions/v1/send-receipt, with any method and sub-path. By default, Only signed-in users (and servers) may call it over HTTP is on: visitors who have not signed in are refused, and servers call it with the secret key.
Triggers#
- Schedule (cron, UTC)
- Five-field cron in UTC, such as
*/15 * * * *, or@hourly,@daily,@weekly,@monthlyand@yearly. Scheduled runs act as the service role. 03:30 UTC is 09:00 in India. - Run when rows change
- Pick a table and
insert,updateordelete, up to 20 entries.ctx.eventholds the new row asrecordand, for updates and deletes, the previous row asold_record. - Run when a user signs up
- Runs for each new user, for a welcome email or a profile row.
Row changes and sign-ups are recorded in the same transaction as the change, so none is lost. Each is delivered at least once and retried with growing pauses, up to 8 attempts, until the function answers with success, so make your function safe to run twice for the same event_id.
Secrets#
Add secrets under Function secrets: a NAME in capitals and its value. Every function reads them from ctx.env, and values are never shown again. Names starting with PLEXIVO_ are reserved. Up to 100 secrets, each up to 8 KB.
Test and watch#
Test runs the function for real, As a visitor or As the service role, and shows its response and logs. Recent runs lists every run with its status and time; logs are kept for 7 days.
Limits#
- Time limit (ms): 10 seconds by default, up to 60 seconds.
- Request body: up to 6 MB.
- Code: up to 512 KB per function. Names are lowercase letters, digits and dashes, starting with a letter.
- Each run is isolated: it can reach the network, but not the file system or other processes.
ctx.env, called from your app and run again by a row change, is the whole backend for a checkout.Next steps#
Updated 27 October 2026