2.1.0
Appwrite 2.1 is the first minor release of the 2.x generation. It opens Appwrite Storage to the S3 ecosystem, adds two OAuth2 providers, teaches image previews to find the subject on their own, and folds in six weeks of fixes across auth, databases, storage, compute and realtime. Upgrading from 2.0.0 is a single command with no collection schema changes.
Highlights
- S3-compatible storage. Any S3 client or SDK can now talk to Appwrite buckets at
/v1/s3, authenticated with AWS Signature V4 headers or presigned URLs using a project API key. Bucket, object, multipart upload, copy, range and AWS chunked requests are covered, and every write goes through the same events, realtime, functions, webhooks, audits and usage metering as the Storage API. (#13515) - Automatic crop gravity. File previews accept
gravity=auto. The newappwrite-autogravityservice detects the focal point of the source image once, caches it per file, and every preview variant crops around it. Set_APP_AUTOGRAVITY_HOSTto enable it; without itautoreturns a clear configuration error and the existing gravities keep working. (#13501) - TikTok and Kakao sign-in join the OAuth2 provider list, and developers can pick the Resend OAuth2 scope. (#13526, #13568)
- Capacitor apps can register
capacitor://as an allowed origin. (#13514) - Console 1.1.78, self-hosted build. A dedicated console image without the cloud CDN origin, so every asset is served by your instance.
- OpenAPI and SDKs. One canonical OpenAPI document now covers every SDK platform, PDF responses are described, and several extensions that only Appwrite's own generator understood are gone:
x-appwrite.type,x-appwrite.produces, the cookies extension and the optional-security extension, replaced by standard alternatives and constrained unions. Enum, timezone and empty-object defaults serialize correctly. (#13512, #13504, #13484, #13524, #13494, #13543, #13577, #13545, #13544, #13502) - Runtimes for Dart 3.13 and Flutter 3.47. (#13503)
- Messaging moved to the module structure, with no route changes. (#13564)
Fixes
Console
- Usage breakdowns resolve names for every resource instead of showing truncated IDs beyond eight functions/sites; lookups batch by query length and preserve successful batches when another fails. (appwrite/vibes#343, Console 1.1.78)
- The terminal stays above the phone keyboard. (appwrite/vibes#339, Console 1.1.77)
Auth and users
- The OAuth2 token flow keeps the current session instead of replacing it. (#13602)
- The password recovery endpoint no longer reveals whether an email exists. (#13438)
- Listing a user's MFA factors reports the recovery code factor. (#13531)
- Invalid scrypt-modified options return a 400 instead of a server error. (#13553)
- The personal-data password validator no longer mutates its own state between checks. (#13532)
- Optional membership fields accept null. (#13541)
- Unsupported team searches return a query error instead of failing silently. (#13566)
- Self-hosted instances enforce the single-organization limit per instance, and editions can lift it. (#13585, #13608)
Redis
- External Redis with a user and password works end to end.
_APP_REDIS_USERwas read but never used, so ACL users failed withWRONGPASS; every Redis client now authenticates with the[user, password]pair when a user is set. The queue publisher and worker consumers, which failed withNOAUTHon any password-protected Redis, receive the credentials andutopia-php/queue2.2.3 actually sends them. Passwords containing@ : / ? #no longer break the connection DSN at boot. (#13622, #13624, fixes #13554)
Databases and TablesDB
- TablesDB webhooks match and deliver on the right events. (#13597)
- Committed transaction events carry surface-correct row and document ids. (#13535)
- Attribute updates keep the column type guard. (#13536)
- GraphQL payloads keep nested data past the escaping depth limit. (#13533)
- A malformed GraphQL SDK query envelope returns 400 with the expected
{"query": "...", "variables": {}}shape instead of a 500. (#13605) - Database operation usage is attributed to the right resource id. (#13523)
- Concurrency sampling keeps the tenant as a string. (#13595)
Storage
- Clean uploads are no longer rejected when the antivirus scanner could not scan them. (#13600)
- Parallel chunked uploads cannot finalize the same file twice. (#13505)
- Email attachments are decrypted before a message is sent. (#13525)
Functions, Sites and VCS
- Manual builds subscribe to artifact callbacks. (#13581)
- The internal jobs endpoint falls back to plain HTTP. (#13601)
- Activating a deployment rebinds the generated branch domain. (#13509)
- Removing a pull request reindexes the provider's remaining pull request ids. (#13530)
- VCS commit statuses and authorize links honour the console URL scheme. (#13476)
- Empty entries in the functions domain list are skipped. (#13529)
- Scheduler rows are removed with their project, and cron expressions validate against the scheduler's own parser. (#13558, #13556)
_APP_COMPUTE_BUILD_SIZE_LIMITis forwarded by the compose file and documented, so the build size limit can be changed on self-hosted installs._APP_FUNCTIONS_BUILD_SIZE_LIMITis marked deprecated. (#13615)
Realtime and events
- Realtime closes its connections on worker exit and folds concurrency over a trailing window. (#13520)
- Presence ids are cast to string in
onClosecleanup. (#13551) - The attribute event is generated before the action event. (#13527)
- Wildcard patterns are deduplicated before events expand. (#13522)
Under the hood
- Error reporting runs on spans. utopia-php/logger is gone.
_APP_LOGGING_CONFIGstill takes asentry://DSN and now ships everySpan::add()attribute with the event, and_APP_LOGGING_FORMATpicksprettyorjsonfor container logs._APP_LOGGING_PROVIDERand_APP_LOGGING_CONFIG_REALTIMEare no longer read. (#13457, #13491) - OPcache and Hyperloop B are on, with HTTP worker recycling to match. (#13487, #13576)
- Compose orchestrator 1.9.2 → 2.1.1, websocket 2.0.2, queue 2.2.3, auth 0.12, system 0.11, Domains 4.0, Client 0.4.4, database 7.3.5. (#13490, #13542, #13578, #13483, #13624, #13583, #13620, #13513, #13492, #13575, #13540)
- Base image 2.0.5 drops the vulnerable
mongodb/mongodbdependency and picks up the libcurl shutdown fix. (#13552, #13496)
Removed
_APP_LOGGING_PROVIDER,_APP_LOGGING_CONFIG_REALTIME,_APP_EXPERIMENT_LOGGING_PROVIDERand_APP_EXPERIMENT_LOGGING_CONFIG. Error reporting is Sentry only; LogOwl, Raygun and AppSignal DSNs are rejected at boot._APP_POOL_ADAPTERfrom the compose file.
Install
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.1.0
Upgrade
Upgrading from 2.0.0 uses the same command with --entrypoint="upgrade", then run the migration:
cd appwrite
docker compose exec appwrite migrate
There is no schema change in this release, so the migration is quick. Existing installs pick up the appwrite-autogravity service and _APP_AUTOGRAVITY_HOST through the upgrade; leave the variable empty if you do not want automatic gravity. If you used _APP_LOGGING_PROVIDER or a realtime-specific DSN, keep a single sentry://PROJECT_ID:KEY@HOST/ DSN in _APP_LOGGING_CONFIG; other providers are no longer supported. Back up your data first.
Contributors
Thank you to everyone who contributed to 2.1.0:
@abnegate @akramcodez @ArnabChatterjee20k @ChiragAgg5k @fogelito @HarshMN2345 @imtia33 @lohanidamodar @loks0n @Meldiron @TorstenDittmann