Jesse A. Green / notebook

Live demo: the DocCompiler guide library as a static, read-only snapshot (October 2026). No backend, no accounts, nothing to submit.

Appwrite Administration & Architecture Guide

Generated May 2026 from appwrite/appwrite at 0aab3e9

AI-generated documentation. The library is checked by sampling (three repositories so far); this guide was not individually reviewed. Verify against the project before relying on it.

Executive Summary

Appwrite is a self-hosted Backend-as-a-Service (BaaS) platform built on PHP 8.3+ with Swoole 6.x for high-concurrency async I/O. It provides authentication, databases (three engines: TablesDB, DocumentsDB, VectorsDB), file storage, serverless functions, static/SSR site hosting, messaging, and real-time WebSocket subscriptions. The platform ships as a Docker Compose stack with Traefik reverse proxy, supporting MariaDB, MongoDB, or PostgreSQL as the underlying database backend. Version 1.9.1 (source commit 0aab3e9, 2026-04-17) is the current stable release.

The codebase spans 2,763 files across two primary namespaces: src/Appwrite/ (platform logic) and app/ (configuration, controllers, initialization). Background processing uses a queue-driven worker architecture handling audits, certificates, deletions, function executions, mail delivery, migrations, statistics, and webhooks.

Important

This guide covers the self-hosted Community Edition. Appwrite Cloud may differ in configuration, scaling, and available features.


1. Architecture Overview

1.1 High-Level Component Map

Internet
  │
  ▼
Traefik (reverse proxy, auto-SSL)
  │
  ├── /v1/*    → Appwrite API (Swoole HTTP server, port 80)
  ├── /console → Console SPA
  └── Realtime → WebSocket server
  │
  ├── Redis (cache, pub/sub, queue broker)
  ├── Database (MariaDB | MongoDB | PostgreSQL)
  ├── Executor (Open Runtimes, function/site builds)
  └── Workers (10 queue consumers)
       ├── Audits        ├── Functions
       ├── Certificates  ├── Mails
       ├── Deletes       ├── Migrations
       ├── Executions    ├── StatsResources
       ├── StatsUsage    └── Webhooks

1.2 Request Lifecycle

  1. Traefik terminates TLS and routes to the Swoole HTTP server.
  2. The general router (app/controllers/general.php) resolves the project from the hostname or X-Appwrite-Project header.
  3. Shared middleware (app/controllers/shared/api/) handles authentication (session, JWT, API key), rate limiting, and abuse detection.
  4. Module-specific service classes (src/Appwrite/Platform/Modules/*/Services/) define route handlers via the utopia-php/platform framework.
  5. Events are published to Redis queues for async processing by workers.
  6. Realtime pushes changes to subscribed WebSocket clients.

1.3 Namespace Map

Namespace Purpose
Appwrite\Platform\Modules\Account User authentication, sessions, MFA
Appwrite\Platform\Modules\Databases TablesDB, DocumentsDB, VectorsDB engines
Appwrite\Platform\Modules\Functions Serverless function CRUD, deployments, executions
Appwrite\Platform\Modules\Sites Static/SSR site hosting with framework detection
Appwrite\Platform\Modules\Storage File buckets, uploads, previews, transformations
Appwrite\Platform\Modules\Teams Team management, memberships, invitations
Appwrite\Platform\Modules\Tokens Resource tokens for files, sites, functions, databases
Appwrite\Platform\Modules\Webhooks Webhook CRUD and delivery
Appwrite\Platform\Modules\Proxy Domain routing rules (API, function, site, redirect)
Appwrite\Platform\Modules\Health Health checks for all subsystems
Appwrite\Platform\Modules\VCS GitHub integration for deployments
Appwrite\Platform\Modules\Console Admin console, redirects, assistant
Appwrite\Platform\Modules\Projects Multi-project management, schedules
Appwrite\Platform\Workers Queue consumer implementations
Appwrite\Platform\Installer Web installer (Swoole server on port 20080)
Appwrite\Auth OAuth2 base, API key validation, MFA, passphrase
Appwrite\Migration Version migration framework (V15–V24)
Appwrite\Event Event publishing (audit, build, certificate, database, etc.)
Appwrite\GraphQL GraphQL endpoint, type system, promise adapters
Executor\Executor HTTP client for Open Runtimes executor

1.4 Database Architecture

Appwrite 1.8+ introduced three database engine types:

Engine Description Use Case
TablesDB Relational model with typed columns, rows, indexes Structured data, recommended for new projects
DocumentsDB Document-based with schemaless collections Legacy/flexible schemas, backward-compatible
VectorsDB Vector embeddings with similarity search AI/ML applications, semantic search

All three engines are backed by the same underlying database backend (MariaDB, MongoDB, or PostgreSQL) via the utopia-php/database abstraction layer. The engine type is set at database creation time and determines the available API surface.

Note

TablesDB is the recommended engine for new projects. The Databases (DocumentsDB) service is deprecated in SDKs from version 1.8 onward but continues to work for existing data.

Shared tables mode — configured via _APP_DATABASE_SHARED_TABLES — allows multiple projects to share the same underlying database tables with tenant isolation via sequence-based partitioning.

1.5 Transaction Support

All three database engines support ACID transactions:

Parameter Value
Default TTL 300 seconds (5 minutes)
Minimum TTL 60 seconds
Maximum TTL 3,600 seconds (1 hour)
Max operations per transaction 100
Max batch size 100

2. System Requirements

2.1 Runtime Dependencies

Component Requirement
PHP >= 8.3.0
Swoole 6.x (ext-swoole)
Redis ext-redis
ImageMagick ext-imagick
Other PHP extensions curl, mbstring, json, yaml, dom, pdo, openssl, zlib, sockets

2.2 Key Composer Dependencies

Package Version Purpose
utopia-php/database 5.x Database abstraction (MariaDB, MongoDB, PostgreSQL)
utopia-php/http 0.34.x HTTP framework (Swoole adapter)
utopia-php/queue 0.17.x Queue broker (Redis-backed)
utopia-php/storage 1.0.x File storage abstraction
utopia-php/cache 1.0.x Cache layer (Redis pool + sharding)
utopia-php/auth 0.5.x Authentication primitives
utopia-php/vcs 3.x GitHub VCS integration
utopia-php/websocket 1.0.x WebSocket server
webonyx/graphql-php 15.31.x GraphQL execution engine
appwrite/php-clamav 2.0.x Antivirus scanning
spomky-labs/otphp 11.x TOTP for MFA
adhocore/jwt 1.1.x JWT token handling
league/csv 9.14.x CSV import/export
matomo/device-detector 6.4.x User-agent parsing
dragonmantank/cron-expression 3.4.x Cron schedule parsing
enshrined/svg-sanitize 0.22.x SVG file sanitization

2.3 Infrastructure Requirements

Component Role Minimum
Docker + Docker Compose Container orchestration v20+
Traefik Reverse proxy, auto-SSL v2+
Redis Cache, queue broker, pub/sub 6+
MariaDB / MongoDB / PostgreSQL Primary data store MariaDB 10.6+, MongoDB 6+, PostgreSQL 15+

3. Configuration Reference

3.1 Environment Variables

Appwrite is configured entirely via environment variables in the .env file. The full variable list is loaded from app/config/variables.php during initialization (app/init/configs.php).

Caution

Environment variable names are prefixed with _APP_. Changing database-related variables on an existing installation requires careful migration. See issue #11902 regarding _APP_DB_HOST redefinition during upgrades.

Core variables:

Variable Purpose Default
_APP_ENV Environment mode development
_APP_DOMAIN Primary domain —
_APP_DOMAIN_TARGET CNAME target for custom domains —
_APP_DOMAIN_FUNCTIONS Functions subdomain —
_APP_DOMAIN_SITES Sites subdomain —
_APP_VERSION Reported version UNKNOWN
_APP_LOCALE Default locale en

Database variables:

Variable Purpose
_APP_DB_HOST Database host
_APP_DB_PORT Database port
_APP_DB_USER Database user
_APP_DB_PASS Database password
_APP_DB_SCHEMA Database schema name
_APP_DATABASE_SHARED_TABLES Comma-separated list of pool names using shared-table mode

Executor variables:

Variable Purpose Default
_APP_EXECUTOR_HOST Open Runtimes executor endpoint —
_APP_EXECUTOR_SECRET Shared secret for executor auth —

Queue variables:

Variable Purpose Default
_APP_QUEUE_PREFETCH_COUNT Batch size for queue consumers 1
_APP_AUDITS_QUEUE_NAME Audit queue name v1-audits
_APP_BUILDS_QUEUE_NAME Build queue name v1-builds
_APP_CERTIFICATES_QUEUE_NAME Certificate queue name v1-certificates
_APP_STATS_USAGE_QUEUE_NAME Usage stats queue name (default in Event class)
_APP_STATS_RESOURCES_QUEUE_NAME Resource stats queue name (default in Event class)

SMTP variables:

Variable Purpose
_APP_SMTP_HOST SMTP server hostname
_APP_SMTP_PORT SMTP port
_APP_SMTP_SECURE TLS mode (tls or ssl)
_APP_SMTP_USERNAME SMTP username
_APP_SMTP_PASSWORD SMTP password

Logging & telemetry:

Variable Purpose
_APP_LOGGING_PROVIDER Error logging provider
_APP_LOGGING_CONFIG Logging provider config
_APP_LOGGING_SERVICE_IDENTIFIER Service name for logs (default: hostname)
_APP_TRACE_PROJECT_ID Project ID for execution tracing
_APP_TRACE_FUNCTION_ID Function ID for execution tracing

3.2 Configuration Files

All configuration is loaded at startup via app/init/configs.php:

Config Key Source File Content
runtimes app/config/runtimes.php Available function runtimes (v5)
runtimes-v2 app/config/runtimes-v2.php Legacy v2 runtimes
events app/config/events.php Webhook/event type definitions
auth app/config/auth.php Auth method configuration
oAuthProviders app/config/oAuthProviders.php OAuth2 provider list (40+)
errors app/config/errors.php Error code definitions (393 error types)
collections app/config/collections.php Internal database schema
frameworks app/config/frameworks.php Site framework definitions
services app/config/services.php Service registry
variables app/config/variables.php Environment variable definitions
specifications app/config/specifications.php Compute specifications
cors app/config/cors.php CORS configuration
roles app/config/roles.php User roles and scopes
projectScopes app/config/scopes/project.php Project-level scopes
organizationScopes app/config/scopes/organization.php Organization-level scopes
accountScopes app/config/scopes/account.php Account-level scopes

3.3 Hard-Coded Limits

These constants are defined in app/init/constants.php and cannot be changed via environment variables:

Constant Value Description
APP_LIMIT_USERS 10,000 Maximum users per project
APP_LIMIT_COUNT 5,000 Maximum count for list queries
APP_LIMIT_LIST_DEFAULT 25 Default items per page
APP_LIMIT_WRITE_RATE_DEFAULT 60 Max writes per rate period
APP_LIMIT_WRITE_RATE_PERIOD_DEFAULT 60s Rate period duration
APP_LIMIT_DATABASE_BATCH 100 Max batch operation size
APP_LIMIT_DATABASE_TRANSACTION 100 Max operations per transaction
APP_LIMIT_ANTIVIRUS 20 MB Max file size for AV scanning
APP_LIMIT_ENCRYPTION 20 MB Max file size for encryption
APP_LIMIT_COMPRESSION 20 MB Max file size for compression
APP_LIMIT_ARRAY_PARAMS_SIZE 100 Max array parameter elements
APP_LIMIT_ARRAY_LABELS_SIZE 1,000 Max label array elements
APP_LIMIT_SUBQUERY 1,000 Max subquery results
APP_LIMIT_SUBSCRIBERS_SUBQUERY 1,000,000 Max subscriber subquery results
APP_LIMIT_USER_PASSWORD_HISTORY 20 Password history depth
APP_LIMIT_USER_SESSIONS_MAX 100 Max sessions per user
APP_LIMIT_USER_SESSIONS_DEFAULT 10 Default sessions per user
APP_DATABASE_ATTRIBUTE_STRING_MAX_LENGTH 1,073,741,824 Max string attribute length
APP_DATABASE_TIMEOUT_MILLISECONDS_API 15,000 ms API query timeout
APP_DATABASE_TIMEOUT_MILLISECONDS_WORKER 300,000 ms Worker query timeout
APP_DATABASE_QUERY_MAX_VALUES 500 Max query values (API)
APP_DATABASE_QUERY_MAX_VALUES_WORKER 5,000 Max query values (worker)
APP_FUNCTION_LOG_LENGTH_LIMIT 1,000,000 Max function log length
APP_FUNCTION_ERROR_LENGTH_LIMIT 1,000,000 Max function error length
MAX_OUTPUT_CHUNK_SIZE 10 MB Response chunk size
APP_STORAGE_READ_BUFFER 20 MB Storage read buffer

3.4 Compute Specifications

Constant Value
APP_COMPUTE_CPUS_DEFAULT 0.5 vCPU
APP_COMPUTE_MEMORY_DEFAULT 512 MB
APP_COMPUTE_SPECIFICATION_DEFAULT S_1VCPU_512MB
APP_COMPUTE_DEPLOYMENT_MAX_RETENTION 36,500 days (~100 years)

4. Deployment & Scaling

4.1 Docker Compose Stack

The production deployment uses Docker Compose with the following services:

Service Image Role
appwrite appwrite/appwrite Main API server (Swoole)
appwrite-realtime appwrite/appwrite WebSocket server
appwrite-worker-* appwrite/appwrite Queue consumers (10 worker types)
appwrite-executor openruntimes/executor Function/site build executor
traefik traefik Reverse proxy with auto-SSL
mariadb mariadb Primary database (or mongodb/postgresql)
redis redis Cache + queue broker + pub/sub

4.2 Web Installer

Appwrite includes a web-based installer (src/Appwrite/Platform/Installer/Server.php) that runs a Swoole HTTP server on port 20080 during initial setup or upgrades.

# Fresh install
php src/Appwrite/Platform/Installer/Server.php --docker

# Upgrade (auto-detects existing config)
php src/Appwrite/Platform/Installer/Server.php --docker --upgrade

# Clean up installer artifacts
composer installer:clean

The installer auto-detects upgrade mode by checking for existing docker-compose.yml and .env files. It also detects the current database backend (MariaDB, MongoDB, or PostgreSQL) from the compose file or environment variables.

Installer steps: env-vars → config-files → docker-compose → docker-containers → account-setup → migration → ssl-certificate.

Lock file: /tmp/appwrite-install-lock.json Config file: /tmp/appwrite-installer-config.json Completion marker: /tmp/appwrite-installer-complete

Warning

The installer binds to 0.0.0.0:20080 by default. Ensure this port is not publicly exposed in production. The installer enforces Content Security Policy headers and CSRF protection.

4.3 Storage Paths

Constant Path Content
APP_STORAGE_UPLOADS /storage/uploads User file uploads
APP_STORAGE_FUNCTIONS /storage/functions Function deployment code
APP_STORAGE_SITES /storage/sites Site deployment files
APP_STORAGE_BUILDS /storage/builds Build artifacts
APP_STORAGE_CACHE /storage/cache File cache
APP_STORAGE_CERTIFICATES /storage/certificates SSL certificates
APP_STORAGE_CONFIG /storage/config Runtime configuration
APP_STORAGE_IMPORTS /storage/imports Temporary CSV import storage

4.4 Scaling Considerations

  • Horizontal worker scaling: Increase the number of worker containers per type. Each worker independently consumes from the Redis queue.
  • Database connection pooling: Appwrite uses utopia-php/pools for connection pooling. Pool sizes are configured via connection DSNs.
  • Redis sharding: Cache adapters support sharding across multiple Redis instances via Utopia\Cache\Adapter\Sharding.
  • Shared tables: Enable _APP_DATABASE_SHARED_TABLES for multi-tenant deployments to reduce database count.
  • Database reconnect: Automatic reconnect with exponential backoff — DATABASE_RECONNECT_SLEEP = 2s, DATABASE_RECONNECT_MAX_ATTEMPTS = 10.
  • Cache reconnect: CACHE_RECONNECT_MAX_RETRIES = 2, CACHE_RECONNECT_RETRY_DELAY = 1000ms.

5. Operations

5.1 Worker Architecture

All background processing flows through Redis-backed queues consumed by dedicated worker processes:

Worker Class Queue Responsibility
Audits Workers\Audits v1-audits Batch audit log writes (60s aggregation interval)
Certificates Workers\Certificates v1-certificates SSL certificate generation via Let's Encrypt, domain verification
Deletes Workers\Deletes v1-deletes Cascading resource deletion (30+ deletion types)
Executions Workers\Executions v1-executions Persist function execution results
Functions Workers\Functions v1-functions Execute serverless functions via Open Runtimes executor
Mails Workers\Mails v1-mails Send transactional emails (verification, recovery, invitation, certificate)
Migrations Workers\Migrations v1-migrations Cross-instance data migration (source/destination processing)
StatsResources Workers\StatsResources configurable Aggregate resource usage statistics
StatsUsage Workers\StatsUsage configurable Aggregate API usage statistics
Webhooks Workers\Webhooks v1-webhooks Deliver webhook HTTP calls

Tip

The Audits worker uses a batch aggregation pattern: it accumulates audit entries for BATCH_AGGREGATION_INTERVAL (60 seconds) before flushing to the database in bulk. The batch size is controlled by _APP_QUEUE_PREFETCH_COUNT.

5.2 Deletion Subsystem

The Deletes worker handles 30+ resource deletion types (all defined as DELETE_TYPE_* constants). Key deletion flows:

  • Project deletion: Cascades through databases, collections, functions, sites, storage, teams, users, webhooks, and all related resources.
  • User deletion: Removes sessions, tokens, memberships, and targets.
  • Database/collection deletion: Removes all documents/rows, attributes, indexes, and storage.
  • Maintenance deletions: Audit logs, abuse records, usage data, expired sessions, expired transactions, CSV exports, realtime connections.

Batch queries use a minimal select set for performance: ['$sequence', '$id', '$collection', '$permissions', '$updatedAt'].

5.3 Event System

Events are published through the Appwrite\Event namespace using Redis queues:

Event Class Queue Trigger
Event\Audit audits All API mutations
Event\Build builds Function/site deployment builds
Event\Certificate certificates Domain verification, SSL generation
Event\Database databases Attribute/index CRUD
Event\Delete deletes Resource deletion
Event\Func functions Function execution triggers
Event\Mail mails Transactional email
Event\Realtime — (direct pub/sub) WebSocket push
Event\Webhook webhooks Webhook delivery

Each event class supports queue name override via environment variables (e.g., _APP_AUDITS_QUEUE_NAME).

5.4 Scheduled Tasks

Appwrite supports cron-scheduled operations for:

  • Function executions: Schedule delayed or periodic function invocations via the scheduledAt parameter. Uses dragonmantank/cron-expression for parsing.
  • Message delivery: Scheduled messaging via the schedules collection.

Schedule resource types: execution, function, message.

5.5 Health Monitoring

The Health service (Appwrite\Platform\Modules\Health) provides checks for:

Endpoint Category What It Checks
DB Database connectivity
Cache Redis cache availability
Queue Queue depth for all worker queues (audits, builds, certificates, databases, deletes, functions, logs, mails, messaging, migrations, stats-resources, stats-usage, webhooks, failed jobs)
Storage Local storage device read/write
Certificate SSL certificate validity
PubSub Redis pub/sub connectivity
AntiVirus ClamAV scanner availability
Time Server time drift detection
Version Software version reporting
Stats System statistics

5.6 Migration Framework

The migration system (src/Appwrite/Migration/Migration.php) manages schema upgrades across Appwrite versions:

Version Range Migration Class
1.0.0 – 1.0.3 V15
1.1.0 – 1.1.2 V16
1.2.x V17
1.3.x V18
1.4.x V19
1.5.x V20
1.6.x V21
1.7.x V22
1.8.x V23
1.9.x V24

Migrations iterate over all project documents in batches of 100, applying schema changes collection by collection.

Caution

After upgrading to 1.9.0+, a missing emailCanonical attribute may cause errors (#11906). Ensure the migration completes successfully and verify the console database schema before serving traffic.

5.7 Cross-Instance Migration

The Migrations worker supports data transfer between Appwrite instances and external sources:

  • Source processing: Reads users (password, phone), teams, databases, documents, storage files from the source.
  • Destination processing: Writes imported data to the target instance.
  • Temporary API keys are generated for migration operations and cleaned up afterward.
  • Resource statistics are tracked per migration for auditing.
  • Filenames are sanitized to prevent path traversal during import.

6. Performance

6.1 Database Timeouts

Context Timeout
API requests 15 seconds (APP_DATABASE_TIMEOUT_MILLISECONDS_API)
Workers 5 minutes (APP_DATABASE_TIMEOUT_MILLISECONDS_WORKER)
CLI tasks 5 minutes (APP_DATABASE_TIMEOUT_MILLISECONDS_TASK)

6.2 Query Limits

Context Max Values
API queries 500 (APP_DATABASE_QUERY_MAX_VALUES)
Worker queries 5,000 (APP_DATABASE_QUERY_MAX_VALUES_WORKER)

6.3 Rate Limiting

Default write rate limiting: 60 writes per 60-second period per resource. Abuse detection uses utopia-php/abuse with time-based database-backed limiters.

6.4 Swoole Coroutines

The entire application runs with Swoole coroutines enabled (SWOOLE_HOOK_ALL), providing async I/O for database, Redis, and network operations without blocking the event loop. The CLI entry point (app/cli.php) also enables coroutines for worker processes.

6.5 Metrics & Observability

Appwrite tracks comprehensive usage metrics (defined as METRIC_* constants):

  • User activity: DAU, WAU, MAU
  • Network: requests, inbound/outbound bytes
  • Database: reads, writes, storage per database/collection
  • Storage: files, transformations, previews per bucket
  • Functions: executions, compute time (MB-seconds), builds
  • Sites: requests, inbound/outbound per site
  • Messaging: sent/failed counts per type and provider
  • Webhooks: sent/failed per webhook
  • Realtime: connections, messages sent, inbound/outbound
  • Embeddings: requests, tokens, duration, errors per model

7. Security

7.1 Authentication Methods

Method Provider Constant Token Length
Email/password SESSION_PROVIDER_EMAIL 256
Anonymous SESSION_PROVIDER_ANONYMOUS —
Magic URL SESSION_PROVIDER_MAGIC_URL 64
Phone OTP SESSION_PROVIDER_PHONE —
OAuth2 (40+ providers) SESSION_PROVIDER_OAUTH2 64
Server token SESSION_PROVIDER_SERVER —
Resource token SESSION_PROVIDER_TOKEN —

7.2 Multi-Factor Authentication (MFA)

  • TOTP via spomky-labs/otphp (RFC 6238)
  • Recovery codes for backup access
  • MFA recent duration: 30 minutes (MFA_RECENT_DURATION = 1800)
  • Challenge/factor validation through Account/Http/Account/MFA/ route handlers

7.3 API Key Types

Type Constant Description
Standard API_KEY_STANDARD Project-scoped API key
Dynamic API_KEY_DYNAMIC Per-request dynamic key (functions)
Organization API_KEY_ORGANIZATION Organization-level access
Account API_KEY_ACCOUNT Account-level access

7.4 Token Expiration

Token Type Expiration
Login (long-lived) 1 year (31,536,000s)
Login (short-lived) 1 hour
Recovery 1 hour
Confirmation 1 hour
OTP 15 minutes
Generic 15 minutes
Resource token 10 years

7.5 JWT Configuration

  • Algorithm: HS256 (RESOURCE_TOKEN_ALGORITHM)
  • Max age: 10 years (RESOURCE_TOKEN_MAX_AGE = 315,360,000s)
  • Leeway: 10 seconds (RESOURCE_TOKEN_LEEWAY)
  • JWT library: adhocore/jwt

7.6 Activity Types

All API activity is classified for audit and abuse detection:

Type Constant Description
User ACTIVITY_TYPE_USER Authenticated user request
Admin ACTIVITY_TYPE_ADMIN Admin mode request
Guest ACTIVITY_TYPE_GUEST Unauthenticated request
Project key ACTIVITY_TYPE_KEY_PROJECT Project API key request
Account key ACTIVITY_TYPE_KEY_ACCOUNT Account API key request
Organization key ACTIVITY_TYPE_KEY_ORGANIZATION Organization API key request

7.7 Content Security Policy

The web installer enforces strict CSP:

default-src 'self'; script-src 'self'; style-src 'self';
img-src 'self' data:; font-src 'self' data:; connect-src 'self';
base-uri 'none'; form-action 'self'; frame-ancestors 'none';

7.8 File Security

  • Antivirus scanning via ClamAV (appwrite/php-clamav), limited to files ≤ 20 MB
  • SVG sanitization via enshrined/svg-sanitize
  • Encryption for files ≤ 20 MB at rest
  • Compression for files ≤ 20 MB
  • Storage read buffer: 20 MB per read operation

7.9 Known Security Issues

  • Command injection in function builds via providerRootDirectory/templateRootDirectory parameters was patched (#11929, CLOSED).
  • Validator state mutation: PersonalData::isValid mutates internal state, causing side effects in concurrent contexts (#11895, OPEN).

8. Developer Internals

8.1 Platform Module System

Appwrite uses the utopia-php/platform framework to organize functionality into modules. Each module follows this structure:

src/Appwrite/Platform/Modules/{Module}/
  ├── Services/          # Route registration (one class per action)
  ├── Http/              # Request/response handling
  │   └── {Resource}/    # Resource-specific endpoints
  └── Workers/           # Module-specific workers (if any)

Services extend Utopia\Platform\Action and register themselves via Service::TYPE_HTTP. Workers extend Utopia\Platform\Action with queue consumption logic.

8.2 Dependency Injection

The application uses Utopia\DI\Container for dependency injection. Key injected services (configured in app/cli.php and shared API init):

Service Type Description
dbForPlatform Database Console/platform database connection
getProjectDB callable Factory returning per-project database instances
getLogsDB callable Factory returning logs database instances
publisher BrokerPool Redis queue publisher
executor Executor Open Runtimes HTTP client
cache Cache Redis cache with sharding
pools Group Connection pool manager
authorization Authorization Auth context (disabled in CLI/worker mode)
bus Bus Event bus for cross-worker communication
telemetry Telemetry Telemetry adapter (NoTelemetry by default)

8.3 Open Runtimes Executor

The Executor class (src/Executor/Executor.php) communicates with the Open Runtimes executor service via HTTP:

  • Runtime creation: createRuntime() — builds and launches a container for a function deployment.
  • Execution: Invokes function code within the runtime container.
  • Runtime migration: Versions v3/v4 are automatically migrated to v5 (if ($version === 'v3' || $version === 'v4') { $version = 'v5'; }).
  • Authentication: Bearer token via _APP_EXECUTOR_SECRET.
  • Addressing: Uses x-opr-addressing-method: anycast-efficient for distributed executor routing.

8.4 GraphQL Support

Appwrite exposes a GraphQL endpoint alongside REST:

  • Parser: app/controllers/api/graphql.php handles both application/json and multipart/form-data requests.
  • Type system: src/Appwrite/GraphQL/Types/ defines custom scalar and object types.
  • Promise adapters: src/Appwrite/GraphQL/Promises/Adapter/ provides async resolution.
  • Engine: webonyx/graphql-php 15.31.x.

8.5 Realtime (WebSocket)

  • WebSocket server runs as a separate container using utopia-php/websocket.
  • Redis pub/sub distributes events to all WebSocket server instances.
  • Clients subscribe to channels: databases.{dbId}.collections.{collId}.documents, account, files, teams, functions, etc.
  • Known issue: WebSocket reconnection lacks exponential backoff (#11939).
  • Metrics tracked: METRIC_REALTIME_CONNECTIONS, METRIC_REALTIME_CONNECTIONS_MESSAGES_SENT.

8.6 OAuth2 Framework

The abstract Appwrite\Auth\OAuth2 class provides the base for all 40+ OAuth2 provider implementations. Each provider implements:

  • getLoginURL() — authorization redirect URL
  • getTokens() — exchange code for tokens
  • refreshTokens() — token refresh
  • getUserID(), getUserEmail(), getUserName() — user info extraction

Provider configuration is loaded from app/config/oAuthProviders.php.

8.7 SDK System

Appwrite generates client SDKs from API specifications using appwrite/sdk-generator. Three built-in SDK bundles are included in the repo:

SDK Path Exported Services
Console SDK public/sdk-console/ Account, Avatars, Databases, Functions, Locale, Storage, Teams
Project SDK public/sdk-project/ Account, Avatars, Databases, Functions, Locale, Storage, Teams
Web SDK public/sdk-web/ Account, Avatars, Databases, Functions, Locale, Storage, Teams

All SDKs export: Client, Query, AppwriteException, Permission, Role, ID.

15+ platform SDKs are maintained separately: Web, Flutter, Android, Apple, Node.js, Python, PHP, Dart, Go, Ruby, .NET, Kotlin, Swift, Deno, Rust.

8.8 Agent Skills

The docs/sdks/agent-skills/ directory contains an npm package (appwrite/agent-skills) following the Agent Skills Open Standard. It provides AI coding agent instructions for 9 languages: TypeScript, Python, PHP, Go, Kotlin, Swift, Ruby, .NET, and Dart. Install with:

npx skills add appwrite/agent-skills

8.9 Sites (Static/SSR Hosting)

The Sites module (Appwrite\Platform\Modules\Sites) supports:

  • Framework auto-detection (Astro, Next.js, etc.) via app/config/frameworks.php
  • Static and SSR deployments with build pipeline
  • Custom start commands for SSR applications
  • Template-based deployments from starter projects
  • VCS integration for automatic deployments on push

8.10 Messaging Subsystem

Multi-channel notification delivery:

Channel Type Constant Description
Email MESSAGE_TYPE_EMAIL Via SMTP (PHPMailer) or Resend adapter
SMS MESSAGE_TYPE_SMS Via configured SMS provider
Push MESSAGE_TYPE_PUSH Push notification delivery

Message routing: internal (system-generated) vs external (user-initiated) via MESSAGE_SEND_TYPE_* constants.

8.11 Proxy & Domain Routing

The Proxy module handles custom domain routing with these rule types:

Rule Type Path Description
API Proxy/Http/Rules/API Route to API endpoints
Function Proxy/Http/Rules/Function Route to function execution
Site Proxy/Http/Rules/Site Route to hosted site
Redirect Proxy/Http/Rules/Redirect URL redirection
Verification Proxy/Http/Rules/Verification Domain ownership verification

Domain rule statuses: created → verifying → verified (or unverified on failure).


9. Integration Points

9.1 GitHub VCS Integration

The VCS module (Appwrite\Platform\Modules\VCS) provides GitHub integration:

  • Repository browsing: List repositories, branches, contents
  • Automatic deployments: Deploy on push via GitHub webhooks
  • Framework detection: Detect project type from repository contents
  • OAuth callback: VCS/Http/GitHub/Callback/ and VCS/Http/GitHub/Authorize/

9.2 Function Runtimes

Functions execute in isolated containers via Open Runtimes. Runtime environment variables available to functions:

Variable Description
APPWRITE_FUNCTION_ID Function ID
APPWRITE_FUNCTION_NAME Function name
APPWRITE_FUNCTION_DEPLOYMENT Active deployment ID
APPWRITE_FUNCTION_PROJECT_ID Project ID
APPWRITE_FUNCTION_RUNTIME_NAME Runtime name
APPWRITE_FUNCTION_RUNTIME_VERSION Runtime version
APPWRITE_FUNCTION_MEMORY Allocated memory
APPWRITE_FUNCTION_CPUS Allocated vCPUs
APPWRITE_VERSION Appwrite server version
APPWRITE_REGION Server region

Request headers available in function context:

Header Description
x-appwrite-trigger Trigger type (http, schedule, event)
x-appwrite-event Event name (for event triggers)
x-appwrite-user-id Requesting user ID
x-appwrite-user-jwt User JWT (if authenticated)
x-appwrite-execution-id Execution ID
x-appwrite-client-ip Client IP address
x-appwrite-key Dynamic API key (for server-side access)

Note

Geo information headers are not currently set for function executions (#9581).

9.3 Email Templates

Mail types for transactional emails:

Type Constant Trigger
Verification MAIL_TYPE_VERIFICATION Email verification request
Magic session MAIL_TYPE_MAGIC_SESSION Magic URL login
Recovery MAIL_TYPE_RECOVERY Password recovery
Invitation MAIL_TYPE_INVITATION Team invitation
Certificate MAIL_TYPE_CERTIFICATE SSL certificate notifications

Templates are loaded from app/config/locale/templates.php with locale-aware rendering. Known issue: session alert templates are broken for non-English locales (#8659).

9.4 CSV Import/Export

CSV handling uses league/csv 9.14.x. Known issue: CSV export may fail to complete for large datasets (#11853). Temporary import files are stored at APP_STORAGE_IMPORTS (/storage/imports).


10. Troubleshooting

10.1 Known Issues (from GitHub)

Issue Status Description
#11906 OPEN Missing emailCanonical attribute after 1.9.0 upgrade
#11902 OPEN _APP_DB_HOST redefined in .env during upgrade
#11939 OPEN WebSocket reconnection needs exponential backoff
#11931 OPEN Scheduled function execution time drift
#11853 OPEN CSV export failing to complete
#8659 OPEN Session alert template broken for non-English
#9581 OPEN Geo headers not set for function execution
#11895 OPEN PersonalData validator mutates internal state

10.2 Upgrade Checklist (1.8.x → 1.9.x)

  1. Backup database and .env file before upgrading.
  2. Run the web installer with --upgrade flag or update Docker images.
  3. Verify _APP_DB_HOST is not redefined in .env (#11902).
  4. Check that the V24 migration completed — look for emailCanonical attribute in the users collection (#11906).
  5. Test OAuth2 flows if configured — redirect URIs may need updating.
  6. Monitor scheduled function execution timing for drift (#11931).

10.3 Database Connection Issues

  • The CLI entry point retries database connections up to 5 times with 3-second sleep intervals before failing.
  • Workers and tasks use DATABASE_RECONNECT_MAX_ATTEMPTS = 10 with DATABASE_RECONNECT_SLEEP = 2s.
  • Log output format: [Error] Timestamp: <ISO 8601>, [Error] Type:, [Error] Message:, [Error] File:, [Error] Line:, [Error] Trace:.

11. Quick Reference

11.1 Development Commands

# Run tests
composer test

# Lint code
composer lint

# Format code
composer format

# Static analysis
composer analyze    # or composer check

# Benchmarks
composer bench

# Start dev installer
composer installer:dev

11.2 Key File Paths

File Purpose
app/cli.php CLI/worker entry point
app/init/constants.php All application constants
app/init/configs.php Configuration loader
app/controllers/general.php Main request router
app/controllers/shared/api/ Shared API middleware
app/config/errors.php Error code definitions (393 types)
app/config/oAuthProviders.php OAuth2 provider registry
app/config/variables.php Environment variable definitions
src/Appwrite/Platform/Installer/Server.php Web installer
src/Appwrite/Migration/Migration.php Version migration framework
src/Executor/Executor.php Open Runtimes client

11.3 Supported Database Backends

Backend Adapter Notes
MariaDB utopia-php/database MySQL adapter Default, most tested
MongoDB utopia-php/database MongoDB adapter Document-native
PostgreSQL utopia-php/database PostgreSQL adapter Relational alternative

11.4 MongoDB Init Script

The included mongo-init.js reads three environment variables:

Variable Purpose
MONGO_INITDB_USERNAME Initial admin username
MONGO_INITDB_PASSWORD Initial admin password
MONGO_INITDB_DATABASE Initial database name

Note

Negative-knowledge omissions (AST extraction):

  • 0 CLI commands were extracted by AST analysis. Appwrite's CLI is a PHP task runner (app/cli.php) that dispatches to platform action classes, not a traditional command-line tool with registered subcommands. No CLI command reference is included.
  • 0 API endpoints were extracted by AST. Routes are registered dynamically via the utopia-php/platform service layer, not as static route definitions parseable by AST. API endpoint tables are not included in this guide.
  • 0 actions and 0 filters were extracted. The platform uses dependency injection and middleware patterns rather than WordPress-style hook/filter systems.