Extending with Hooks
PocketBase hooks let you run custom JavaScript on the server — right inside your instance. Add API routes, react to record changes, schedule cron jobs, or send emails, all without deploying a separate backend.
On PocketBase Cloud you write and manage hooks directly in the dashboard: open your instance and go to the Hooks tab.
Creating a hook
- Open your PocketBase instance in the dashboard
- Go to the Hooks tab
- Click New Hook, give the file a name ending in
.pb.js(e.g.,main.pb.js) - Write your code and save — the instance reloads hooks automatically
Example: a custom API route
routerAdd("GET", "/api/hello/{name}", (e) => {
const name = e.request.pathValue("name");
return e.json(200, { message: `Hello ${name}!` });
});
Your route is immediately available at
https://<instance-name>.pocketbasecloud.com/api/hello/world.
Example: react to record changes
Run logic whenever a record is created, updated, or deleted:
onRecordCreate((e) => {
// runs before the record is persisted — you can still modify it
e.record.set("slug", e.record.get("title").toLowerCase().replaceAll(" ", "-"));
e.next();
}, "posts");
onRecordAfterCreateSuccess((e) => {
// runs after the record is saved
console.log("new post:", e.record.id);
e.next();
}, "posts");
Example: scheduled cron jobs
cronAdd("cleanup", "0 3 * * *", () => {
const records = $app.findRecordsByFilter(
"sessions",
"created < @yesterday",
"-created",
200,
0
);
for (const record of records) {
$app.delete(record);
}
});
Example: send an email
onRecordAfterCreateSuccess((e) => {
const message = new MailerMessage({
from: { address: e.app.settings().meta.senderAddress },
to: [{ address: e.record.email() }],
subject: "Welcome!",
html: "<p>Thanks for signing up.</p>",
});
e.app.newMailClient().send(message);
e.next();
}, "users");
What hooks can access
Hooks run in PocketBase’s embedded JavaScript VM with access to:
$app— the full PocketBase app instance (query, create, update records)routerAdd— register custom HTTP routesonRecord*event handlers — before/after create, update, deletecronAdd— cron-style scheduled jobs$http.send()— make outbound HTTP requests to third-party APIs$os,$filesystem,$security— utility namespaces
See the PocketBase JSVM documentation for the complete API.
When to use a backend instead
Hooks are perfect for lightweight logic tied to your data. For heavier workloads — long-running jobs, large dependencies, websockets, or code you want to develop and test locally as a normal project — deploy a dedicated backend alongside your instance.