Overview
Appwrite is a self-hosted or cloud-hosted backend-as-a-service (BaaS) that provides a complete set of APIs and tools for building web and mobile applications. It offers user authentication with multiple providers, a document-based database, file storage, serverless functions, realtime events, and push messaging, all accessible through REST APIs and client/server SDKs.
Appwrite supports over 10 programming language SDKs including JavaScript, Flutter, Swift, Kotlin, Python, and Ruby. It runs as a set of Docker containers and provides a web-based console for managing projects, users, and resources. The platform is designed to be a self-hosted alternative to Firebase with full control over your data.
Installation
Self-Hosted (Docker)
# One-line 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:1.6
# Or using Docker Compose manually
mkdir appwrite && cd appwrite
curl -o docker-compose.yml https://appwrite.io/install/compose
curl -o .env https://appwrite.io/install/env
# Edit .env with your settings
nano .env
# Start the services
docker compose up -d
# Console available at http://localhost:80
CLI Installation
# Install via npm
npm install -g appwrite-cli
# Or via script
curl -sL https://appwrite.io/cli/install.sh | bash
# Login to your instance
appwrite login
# Initialize a project
appwrite init project
Core Services
Authentication
# Create account via API
curl -X POST "https://cloud.appwrite.io/v1/account" \
-H "Content-Type: application/json" \
-H "X-Appwrite-Project: PROJECT_ID" \
-d '{"userId":"unique()","email":"user@example.com","password":"password123","name":"Alice"}'
# Create email session
curl -X POST "https://cloud.appwrite.io/v1/account/sessions/email" \
-H "Content-Type: application/json" \
-H "X-Appwrite-Project: PROJECT_ID" \
-d '{"email":"user@example.com","password":"password123"}'
JavaScript SDK
import { Client, Account, Databases, Storage, ID, Query } from "appwrite"
const client = new Client()
.setEndpoint("https://cloud.appwrite.io/v1")
.setProject("PROJECT_ID")
// Authentication
const account = new Account(client)
await account.create(ID.unique(), "user@example.com", "password123", "Alice")
await account.createEmailPasswordSession("user@example.com", "password123")
const user = await account.get()
// OAuth login
account.createOAuth2Session("google", "http://localhost:3000", "http://localhost:3000/fail")
Database Operations
const databases = new Databases(client)
// Create a document
const doc = await databases.createDocument(
"DATABASE_ID",
"COLLECTION_ID",
ID.unique(),
{
title: "My Post",
content: "Hello World",
published: true,
tags: ["news", "tech"],
}
)
// List documents with queries
const posts = await databases.listDocuments("DATABASE_ID", "COLLECTION_ID", [
Query.equal("published", true),
Query.orderDesc("$createdAt"),
Query.limit(20),
Query.offset(0),
])
// Get a single document
const post = await databases.getDocument("DATABASE_ID", "COLLECTION_ID", "DOCUMENT_ID")
// Update a document
await databases.updateDocument("DATABASE_ID", "COLLECTION_ID", "DOCUMENT_ID", {
title: "Updated Title",
})
// Delete a document
await databases.deleteDocument("DATABASE_ID", "COLLECTION_ID", "DOCUMENT_ID")
Query Operators
| Operator | Example | Description |
|---|
Query.equal() | Query.equal("status", "active") | Exact match |
Query.notEqual() | Query.notEqual("role", "admin") | Not equal |
Query.greaterThan() | Query.greaterThan("age", 18) | Greater than |
Query.lessThan() | Query.lessThan("price", 100) | Less than |
Query.search() | Query.search("title", "hello") | Full-text search |
Query.contains() | Query.contains("tags", ["news"]) | Array contains |
Query.between() | Query.between("age", 18, 65) | Range match |
Query.isNull() | Query.isNull("deletedAt") | Is null |
Query.isNotNull() | Query.isNotNull("email") | Is not null |
Query.startsWith() | Query.startsWith("name", "Al") | String starts with |
Query.orderAsc() | Query.orderAsc("name") | Sort ascending |
Query.orderDesc() | Query.orderDesc("$createdAt") | Sort descending |
Query.limit() | Query.limit(25) | Limit results |
Query.offset() | Query.offset(50) | Skip results |
File Storage
const storage = new Storage(client)
// Upload a file
const file = await storage.createFile(
"BUCKET_ID",
ID.unique(),
document.getElementById("fileInput").files[0]
)
// Get file URL for preview
const url = storage.getFilePreview("BUCKET_ID", "FILE_ID", 400, 300)
// Download a file
const download = storage.getFileDownload("BUCKET_ID", "FILE_ID")
// List files
const files = await storage.listFiles("BUCKET_ID")
// Delete a file
await storage.deleteFile("BUCKET_ID", "FILE_ID")
Configuration
CLI Commands
| Command | Description |
|---|
appwrite login | Authenticate with your instance |
appwrite init project | Initialize project in current directory |
appwrite init collection | Create a collection configuration |
appwrite init function | Scaffold a new function |
appwrite deploy | Deploy functions and collections |
appwrite deploy --all | Deploy everything |
appwrite console | Open the web console |
Environment Variables (.env)
_APP_ENV=production
_APP_DOMAIN=appwrite.yourdomain.com
_APP_DOMAIN_TARGET=appwrite.yourdomain.com
_APP_OPENSSL_KEY_V1=your-secret-key
_APP_DB_HOST=mariadb
_APP_DB_PORT=3306
_APP_DB_SCHEMA=appwrite
_APP_DB_USER=user
_APP_DB_PASS=password
_APP_REDIS_HOST=redis
_APP_REDIS_PORT=6379
_APP_SMTP_HOST=smtp.yourdomain.com
_APP_SMTP_PORT=587
_APP_SMTP_USERNAME=mail@yourdomain.com
_APP_SMTP_PASSWORD=smtp-password
_APP_STORAGE_LIMIT=30000000
_APP_FUNCTIONS_SIZE_LIMIT=30000000
_APP_FUNCTIONS_TIMEOUT=900
Advanced Usage
Serverless Functions
// functions/hello/src/main.js
export default async ({ req, res, log, error }) => {
if (req.method === "GET") {
return res.json({ message: "Hello from Appwrite Functions!" })
}
if (req.method === "POST") {
const { name } = JSON.parse(req.body)
log(`Processing request for ${name}`)
return res.json({ message: `Hello, ${name}!` })
}
return res.json({ error: "Method not allowed" }, 405)
}
# Deploy a function
appwrite deploy function
# Execute a function
curl -X POST "https://cloud.appwrite.io/v1/functions/FUNCTION_ID/executions" \
-H "Content-Type: application/json" \
-H "X-Appwrite-Project: PROJECT_ID" \
-H "X-Appwrite-Key: API_KEY" \
-d '{"body":"{\"name\":\"Alice\"}"}'
Realtime Subscriptions
// Subscribe to document changes
client.subscribe(
["databases.DATABASE_ID.collections.COLLECTION_ID.documents"],
(response) => {
console.log(response.events) // e.g., ["databases.*.collections.*.documents.*.create"]
console.log(response.payload) // the document data
}
)
// Subscribe to file changes
client.subscribe(["buckets.BUCKET_ID.files"], (response) => {
console.log("File event:", response.events)
})
// Subscribe to account changes
client.subscribe(["account"], (response) => {
console.log("Account event:", response.events)
})
Server-Side SDK (Node.js)
import { Client, Databases, Users } from "node-appwrite"
const client = new Client()
.setEndpoint("https://cloud.appwrite.io/v1")
.setProject("PROJECT_ID")
.setKey("API_KEY")
const users = new Users(client)
const userList = await users.list()
const databases = new Databases(client)
await databases.createDocument("DB_ID", "COLL_ID", ID.unique(), {
title: "Server-created doc",
})
Troubleshooting
| Issue | Solution |
|---|
| Docker containers not starting | Check Docker resources; ensure ports 80/443 are free |
| CORS errors | Add your domain to project platforms in the console |
| File upload size exceeded | Increase _APP_STORAGE_LIMIT in .env |
| Function timeout | Increase _APP_FUNCTIONS_TIMEOUT; optimize function code |
| Authentication errors | Verify project ID and API endpoint; check session validity |
| Realtime not connecting | Ensure WebSocket port is accessible; check SSL configuration |
| Slow database queries | Add indexes to frequently queried attributes in the console |
| Email not sending | Configure SMTP settings in .env; verify credentials |
| SSL certificate issues | Ensure _APP_DOMAIN matches your SSL certificate domain |