Every app eventually needs server-side logic that does not fit neatly into a database write or a storage upload. Sending an email after a user signs up, resizing an image after it is uploaded, charging a customer after an order is placed. This is the gap that Appwrite Functions fills.
Appwrite Functions run your custom code inside isolated containers, triggered by HTTP requests, events, schedules, or SDK calls. They give you full control over server-side logic without managing servers, and they integrate directly with the rest of your Appwrite project.
What Appwrite Functions are
Each function is a self-contained unit of code. You define the runtime (Node.js, Python, Go, Dart, PHP, Ruby, and more), write your handler, and deploy. Appwrite wraps it in an isolated container with its own environment variables, its own URL, and its own execution history.
Functions are not long-running services. They start, execute, and stop. For persistent workloads, you would use a separate server. For discrete tasks triggered by an event or a schedule, functions are the right tool.
Triggers
Appwrite Functions support five trigger types. Choosing the right trigger is the first design decision for any function.
HTTP requests
Every function gets a unique URL. Any HTTP request to that URL triggers the function. The function receives the full request (method, headers, body, query parameters) and returns a response.
This is the most flexible trigger. Use it to build webhooks, REST endpoints, API proxies, or any server-side endpoint your client needs to call directly.
SDK execution
Client and server SDKs can trigger a function programmatically:
import { Functions } from "appwrite";
const functions = new Functions(client);
const execution = await functions.createExecution({
functionId: "[FUNCTION_ID]",
body: JSON.stringify({ userId: "abc123" }),
async: false,
path: "/",
method: "POST"
});
console.log(execution.responseBody);
SDK-triggered functions behave identically to HTTP-triggered functions. The difference is that SDK calls go through Appwrite's auth layer, so the function context includes the calling user's session.
Server events
Appwrite emits events when things happen inside your project: a row is created, a file is uploaded, a user signs up. You can configure a function to fire on any of these events.
Event-triggered functions receive the event name and the full resource payload in the request body. The x-appwrite-event header tells the function which event fired.
Examples of events you can react to:
databases.[DATABASE_ID].tables.[TABLE_ID].rows.*.createfires when any row is created in a tablestorage.[BUCKET_ID].files.*.createfires when a file is uploadedusers.*.createfires when a new user registersusers.*.sessions.*.createfires on every new login
This is the right trigger for side effects: post-processing uploads, sending notifications, syncing data to external systems.
Scheduled executions (cron)
Functions can run on a cron schedule, as frequently as once every minute. The cron syntax is standard:
* * * * * every minute
0 * * * * every hour
0 9 * * 1 every Monday at 9am UTC
Use scheduled functions for recurring jobs: daily reports, cleanup tasks, cache refreshes, subscription renewals, and anything else that needs to run on a timer rather than in response to an event.
Delayed executions
SDK execution supports a delay parameter that schedules the function to run at a future time. This is useful for deferred processing, follow-up emails a set number of hours after a user action, or any task that should happen later rather than immediately.
Execution modes: synchronous vs asynchronous
Every function execution is either synchronous or asynchronous. This matters for how your calling code behaves.
Synchronous execution
The caller waits for the function to complete and receives the response body directly. Synchronous executions have a hard 30-second timeout. If the function does not complete within 30 seconds, the execution is terminated.
Synchronous mode is the right choice when:
- The caller needs the function's output to proceed
- The function is fast enough to complete within 30 seconds
- You are building an API endpoint that must return data
const execution = await functions.createExecution({
functionId: "[FUNCTION_ID]",
body,
async: false
});
// execution.responseBody contains the function's output
Asynchronous execution
The caller receives an execution ID immediately and does not wait for the function to finish. The function runs in the background. You can check its status later by fetching the execution by ID.
Asynchronous mode is the right choice when:
- The task takes longer than 30 seconds
- The caller does not need the result immediately
- You are processing uploads, sending emails, or running batch jobs
const execution = await functions.createExecution({
functionId: "[FUNCTION_ID]",
body,
async: true
});
// execution.status will be "waiting" or "processing"
// poll later with functions.getExecution(functionId, execution.$id)
HTTP-triggered functions always behave synchronously from the HTTP client's perspective: the connection stays open until the function returns a response or times out.
Deployment
Manual deployment
You can upload a compressed archive of your function code directly in the Appwrite Console or via the CLI. This is the fastest way to test a function, but it does not version your code or integrate with your development workflow.
Deploy from Git
Appwrite Functions support continuous deployment from GitHub, GitLab, and Bitbucket. Connect a repository, specify the branch and build command, and Appwrite automatically deploys a new version every time you push.
Git deployment is the recommended approach for production functions. It gives you:
- Version history tied to your commits
- Automatic redeployment on push
- Rollback to any previous deployment
- Code review via pull requests before deployment
Build commands and environment variables
Each function has its own build command (for installing dependencies and compiling code) and its own set of environment variables. Environment variables are encrypted at rest and injected into the function at runtime. Never hard-code secrets; always use environment variables.
Customer identity without the hassle
Add secure authentication in minutes, not weeks.
Built-in security and compliance
Multiple login methods
Custom authentication flows
Multi-factor authentication
Permissions
Client SDK execution
When a client calls a function via the SDK, Appwrite checks whether the function has the execute permission for the calling user's role. By default, no client can execute a function. You must explicitly grant execute permission.
To allow all authenticated users to execute a function:
[Permission.execute(Role.users())]
To restrict execution to a specific team:
[Permission.execute(Role.team("teamABC"))]
Server SDK execution
Server SDK calls with an API key bypass function-level permissions, subject to the API key's scope. The API key must have the functions.executions.write scope to trigger a function.
HTTP endpoint execution
Direct HTTP calls to the function URL also go through the permission check. If the function is not publicly executable (Role.any()), unauthenticated HTTP calls will be rejected.
Use cases
Webhooks. Functions are natural webhook receivers. Point a Stripe, Twilio, or GitHub webhook at your function URL. The function receives the payload, validates the signature, and updates your Appwrite database.
Post-processing uploads. Trigger a function on storage.*.files.*.create to resize images, extract metadata, run virus scans, or generate thumbnails immediately after upload.
Email and notification delivery. Trigger a function on user creation or order completion to send transactional email via SendGrid, Resend, or any email API. Keep your email credentials in function environment variables.
Scheduled reports. Run a function every morning to aggregate the previous day's data, write a summary row, and send a report email to stakeholders.
Third-party API proxies. Expose a function as an HTTP endpoint that calls a third-party API with a secret key. Clients call your function; the function calls the external API. API keys never leave the server.
Data validation and enrichment. Trigger a function on row creation to validate fields, enrich data from external sources, or enforce business rules that cannot be expressed as database constraints.
Get started with Appwrite Functions
Appwrite Functions give you server-side execution that integrates directly with your Appwrite project, scales automatically, and requires no server management. Every trigger type, execution mode, and runtime is available on Appwrite Cloud.



