Appwrite 2.5.0. Source highlight: Appwrite 2.5 lets you turn on passkeys for your projects from the Console, including in native Android apps. Functions can now run on an interval instead of a cron expression. Function runtimes no longer crash-loop after the executor restarts, the bundled ClickHouse does far less work under load, an
Check the source notes against the package and APIs you use before upgrading.
๐ Product & Engineering Leads
Use the documented changes to assess relevance to your product; release frequency alone is not a quality measure.
โ๏ธ DevOps & Security
Verify the target version, runtime requirements and rollback procedure in the official documentation.
โจ New Features & Capabilities (1)
**Console 1.2.74.** Adds project passkeys, function intervals, Android signing certificates and resizable row fields. Signing in to a self-hosted Console is now email and password only, without the OAuth and passkey buttons. (#14434)
๐ง Bug Fixes & Patches (6)
**Interval schedules for functions.** A function can run every N minutes instead of on a cron expression. Each function gets a fixed slot inside its interval derived from its ID, so many hourly functions spread across the hour instead of all firing at :00. Set it under Settings โบ Executions. (#14231, #14307, #14311, #14319)
Row text fields in TablesDB, DocumentsDB and VectorsDB can be resized. (#14345)
Signing in with an OAuth2 provider or ID token that matches an existing unverified account by email marks it verified. (#14283)
Inviting the dotted or aliased form of a canonical email invites the existing account instead of failing with 409 or 400. Yahoo hyphens stay part of the address. (#14172, fixes #14230)
A removed team member's client now receives the membership delete realtime event. (#13780, #14210, fixes #13768)
`PATCH /v1/teams/:teamId/memberships/:membershipId/status` is rate limited to 10 requests per IP and membership. (#14405)
๐ View Raw Release Notes (Original Developer Log)

Appwrite 2.5 lets you turn on passkeys for your projects from the Console, including in native Android apps. Functions can now run on an interval instead of a cron expression. Function runtimes no longer crash-loop after the executor restarts, the bundled ClickHouse does far less work under load, and the installer keeps your `docker-compose.override.yml` and custom ports. It ships with the 1.2.74 self-hosted Console (was 1.2.55).
Upgrading from 2.4.0 is one command plus `migrate`. Nothing needs to be changed by hand.
### Highlights
- **Passkeys for your projects**, enabled with a domain picked from your web platforms, and in Android apps by their signing certificate. (#14310, #14313, #14353, #14362, #14394, #14395, #14400)
- **Interval schedules for functions.** A function can run every N minutes instead of on a cron expression. Each function gets a fixed slot inside its interval derived from its ID, so many hourly functions spread across the hour instead of all firing at :00. Set it under Settings โบ Executions. (#14231, #14307, #14311, #14319)
- **Console 1.2.74.** Adds project passkeys, function intervals, Android signing certificates and resizable row fields. Signing in to a self-hosted Console is now email and password only, without the OAuth and passkey buttons. (#14434)
- **Runtimes survive executor restarts.** The executor moves from 0.29.0 to 1.1.2. A restarted executor used to lose track of running runtimes and delete their code, so the next time one exited it restarted forever with `Code path /tmp/code.tar.gz not found`. Untracked runtimes are now removed on startup. (#14361)
- **Less ClickHouse load.** The usage worker batches writes across messages instead of one `INSERT` per request or execution, which kept the bundled ClickHouse at up to two cores on busy installs. (#14291)
### Fixes
**Console**
- Row text fields in TablesDB, DocumentsDB and VectorsDB can be resized. (#14345)
**Auth and teams**
- Signing in with an OAuth2 provider or ID token that matches an existing unverified account by email marks it verified. (#14283)
- Inviting the dotted or aliased form of a canonical email invites the existing account instead of failing with 409 or 400. Yahoo hyphens stay part of the address. (#14172, fixes #14230)
- A removed team member's client now receives the membership delete realtime event. (#13780, #14210, fixes #13768)
- `PATCH /v1/teams/:teamId/memberships/:membershipId/status` is rate limited to 10 requests per IP and membership. (#14405)
**Databases and TablesDB**
- `getRow` returns the committed row right after a transaction commit instead of a stale copy or a 404. (#14201, fixes #14173)
- On Postgres, `trigram` is a new index type that serves `startsWith`, `contains` and `endsWith`. Other databases reject it. (#14108, fixes #14088)
- A row too large for one of its indexes returns `400 column_limit_exceeded` (`attribute_limit_exceeded` for collections) instead of a 500. (#14374, fixes #14335)
- Operators on encrypted columns return 400 instead of corrupting the stored value. (#14250, #14375, fixes #14218)
- `listColumns` and `listAttributes` report `encrypt` for every string type, so the Console masks encrypted varchar and text values. (#14413)
- Bulk, upsert and transaction commit events no longer carry the internal `$collection` and `$tenant` fields. (#14216)
- Adding operations to a transaction has the same rate limit as creating a document. (#14405)
**Functions**
- Synchronous and queued executions, and execution events from the worker, return `$createdAt` and `$updatedAt` in ISO 8601 like every other route. (#14295, #14316, fixes #14296, #14317)
**Storage**
- Image previews in encrypted buckets check `_APP_STORAGE_PREVIEW_LIMIT` against the uploaded size, so images between 15 MB and 20 MB preview again. (#14284)
- `PUT /v1/storage/buckets/:bucketId/files/:fileId` has its rate limit back. (#14405)
**Webhooks**
- `authPassword` accepts up to 2048 characters, and oversized usernames or URLs return 400 instead of 500. (#14356)
**Avatars**
- Favicons resolve against the page a redirect lands on. (#14211, fixes #13985)
**Migrations**
- Migrations carry function intervals, deployment retention, secret variables, site scopes and start commands, file folders, and more project policies. Function variables are no longer mixed up with a site's. (#14382)
- A migration whose source or destination stops answering fails instead of staying in `processing`. (#14330, fixes #14331)
**Installer and workers**
- `install` and `upgrade` keep `docker-compose.override.yml`. (#14262)
- `upgrade` keeps custom HTTP/HTTPS ports and the HTTPS setting, and ports can be bound to one interface such as `127.0.0.1:80`. (#14345, fixes #14346)
### Under the hood
- utopia-php/database 7.4.2, migration 2.1.0, svg-sanitize 1.0 and sdk-for-php 30.2.2. (#14375, #14382, #14285)
- API specs emit response model defaults and typed array items, so SDK models fill fields that older servers don't send. (#14265, #14266, #14267, #14357, #14368, #14370)
- `Console` and the base `Validator` moved into `Utopia\Console` and `Utopia\Validator`. (#14261, #14263)
- CI runs only the e2e lanes a change can affect, behind required gate jobs and a merge queue. (#14298, #14301, #14391)
### Removed
Nothing.
### Install
```bash
docker run -it --rm \
--volume /var/run/docker.sock:/var/run/docker.sock \
--volume "$(pwd)"/appwrite:/usr/src/code/appwrite:rw \
--entrypoint="install" \
appwrite/appwrite:2.5.0
```
### Upgrade
Run the same command with `--entrypoint="upgrade"`, then migrate:
```bash
cd appwrite
docker compose exec appwrite migrate
```
The migration stays on V25. It adds the function `interval` and Android platform `fingerprints` columns and widens the webhook `httpPass` column, and it takes longer the more projects you have. The new compose file moves `openruntimes/executor` to 1.1.2; existing runtime containers are removed when it starts and cold-start on their next execution.
Migrating a project to another install or to Cloud doesn't carry the passkey policy, the password rotation policy or Android signing certificate fingerprints yet, so set them again on the destination. Migrated team memberships get new IDs, so custom membership IDs aren't kept.
If you upgrade with `--use-existing-config`, change the executor image to `openruntimes/executor:1.1.2` yourself. **Back up your data first.**
### Contributors
Thank you to everyone who contributed to 2.5.0:
@ChiragAgg5k @HarshMN2345 @loks0n @levivannoort @eldadfux @ItsRoy69 @imtia33 @Indra55 @okxint @adityaoberai @abnegate @atharvadeosthale @aishwaripahwa12