Rust

by appwriteab3c90b37c95No license10 starsListed Oct 8, 2026Updated Oct 8, 2026Repository updated 7 weeks ago

Appwrite Rust SDK skill. Use when building server-side Rust applications with Appwrite. Covers async client setup with API keys, user management, TablesDB database/table/row operations, file storage, function executions, permissions, queries, and error handling. Uses the crates.io `appwrite` package and Tokio.

Instructions onlySoftware Development
AI-generated overview

Guides server-side Rust development with the Appwrite SDK, covering client setup, users, TablesDB, storage, functions and errors.

What it does
This skill provides reference instructions and code examples for building server-side Rust applications with the Appwrite SDK. It covers async client setup using an API key and Tokio, user management, TablesDB database, table, column and row operations, queries, file storage, function executions, permissions and error handling. It produces guidance and code snippets rather than scripts or generated files.
When to use it
Use it when writing or reviewing server-side Rust code that integrates Appwrite. It is suited to tasks involving Appwrite users, databases, storage buckets, function executions or permissions from a Rust backend.
Requirements
Requires the crates.io appwrite package, Tokio with full features, and serde_json. Server-side authentication needs an Appwrite endpoint, project ID and API key, plus network access to the Appwrite service. No scripts are shipped; it is instructions only.

Appwrite Rust SDK

Installation

bash
cargo add appwritecargo add tokio --features fullcargo add serde_json

Or add dependencies manually:

toml
[dependencies]appwrite = "0.3.0"tokio = { version = "1", features = ["full"] }serde_json = "1"

Setting Up the Client

The Rust SDK is async. Use it from a Tokio runtime and authenticate server-side with an API key.

rust
use appwrite::Client;use std::env;
let client = Client::new()    .set_endpoint("https://<REGION>.cloud.appwrite.io/v1")    .set_project(env::var("APPWRITE_PROJECT_ID")?)    .set_key(env::var("APPWRITE_API_KEY")?);

Complete server skeleton

rust
use appwrite::query::Query;use appwrite::services::Users;use appwrite::Client;use std::env;
#[tokio::main]async fn main() -> Result<(), Box<dyn std::error::Error>> {    let client = Client::new()        .set_endpoint("https://<REGION>.cloud.appwrite.io/v1")        .set_project(env::var("APPWRITE_PROJECT_ID")?)        .set_key(env::var("APPWRITE_API_KEY")?);
    let users = Users::new(&client);    let _list = users        .list(Some(vec![Query::limit(25).to_string()]), None, Some(true))        .await?;
    Ok(())}

Code Examples

User Management

rust
use appwrite::id::ID;use appwrite::query::Query;use appwrite::services::Users;
let users = Users::new(&client);
// Create userlet _user = users    .create(        ID::unique(),        Some("[email protected]"),        None,        Some("password123"),        Some("User Name"),    )    .await?;
// List userslet _list = users    .list(Some(vec![Query::limit(25).to_string()]), None, Some(true))    .await?;
// Get userlet _fetched = users.get("[USER_ID]").await?;
// Delete userusers.delete("[USER_ID]").await?;

Database Operations

Note: Use TablesDB for new code. Only use Databases if the existing project explicitly depends on the legacy Databases API.

Rust SDK calling convention: Methods are async, use positional parameters, and represent optional API parameters as Option<T>. Pass None for optional values you are not setting.

rust
use appwrite::id::ID;use appwrite::permission::Permission;use appwrite::query::Query;use appwrite::role::Role;use appwrite::services::TablesDB;use serde_json::json;
let tables_db = TablesDB::new(&client);
// Create databaselet _database = tables_db    .create(ID::unique(), "My Database", Some(true))    .await?;
// Create tablelet _table = tables_db    .create_table(        "[DATABASE_ID]",        ID::unique(),        "articles",        Some(vec![            Permission::read(Role::any()).to_string(),            Permission::create(Role::users(None)).to_string(),        ]),        Some(true),        Some(true),        None,        None,    )    .await?;
// Create rowlet _row = tables_db    .create_row(        "[DATABASE_ID]",        "[TABLE_ID]",        ID::unique(),        json!({            "title": "Hello World",            "done": false        }),        None,        None,    )    .await?;
// Query rowslet _rows = tables_db    .list_rows(        "[DATABASE_ID]",        "[TABLE_ID]",        Some(vec![            Query::equal("done", false).to_string(),            Query::limit(10).to_string(),        ]),        None,        Some(true),        None,    )    .await?;
// Get rowlet _row = tables_db    .get_row("[DATABASE_ID]", "[TABLE_ID]", "[ROW_ID]", None, None)    .await?;
// Update rowlet _updated = tables_db    .update_row(        "[DATABASE_ID]",        "[TABLE_ID]",        "[ROW_ID]",        Some(json!({ "done": true })),        None,        None,    )    .await?;
// Delete rowtables_db    .delete_row("[DATABASE_ID]", "[TABLE_ID]", "[ROW_ID]", None)    .await?;
String Column Types

Note: The legacy string column type is deprecated. Use explicit string column types for new tables.

TypeMax charactersIndexingStorage
varchar16,383Full index (if size <= 768)Inline in row
text16,383Prefix onlyOff-page
mediumtext4,194,303Prefix onlyOff-page
longtext1,073,741,823Prefix onlyOff-page
  • varchar is stored inline and counts toward the 64 KB row size limit. Prefer it for short, indexed fields like names, slugs, and identifiers.
  • text, mediumtext, and longtext are stored off-page, so they do not consume the row size budget. size is not required for these types.
rust
use appwrite::enums::{OrderBy, TablesDBIndexType};
// Short, indexed stringlet _title = tables_db    .create_varchar_column(        "[DATABASE_ID]",        "[TABLE_ID]",        "title",        255,        true,        None,        None,        None,    )    .await?;
// Off-page longer textlet _summary = tables_db    .create_text_column("[DATABASE_ID]", "[TABLE_ID]", "summary", false, None, None, None)    .await?;
let _body = tables_db    .create_mediumtext_column("[DATABASE_ID]", "[TABLE_ID]", "body", false, None, None, None)    .await?;
let _raw_data = tables_db    .create_longtext_column("[DATABASE_ID]", "[TABLE_ID]", "raw_data", false, None, None, None)    .await?;
// Index only the varchar column fully.let _index = tables_db    .create_index(        "[DATABASE_ID]",        "[TABLE_ID]",        "title_idx",        TablesDBIndexType::Key,        vec!["title"],        Some(vec![OrderBy::Asc]),        Some(vec![255]),    )    .await?;

Query Methods

TablesDB methods accept Option<Vec<String>> for queries. Convert each Query to a string.

rust
use appwrite::query::Query;use serde_json::Value;
let queries = vec![    Query::equal("status", "published").to_string(),    Query::not_equal("archived", true).to_string(),    Query::greater_than("views", 100).to_string(),    Query::less_than_equal("priority", 5).to_string(),    Query::between("score", 1, 100).to_string(),    Query::is_not_null("publishedAt").to_string(),    Query::search("title", "rust appwrite").to_string(),    Query::contains("tags", "rust").to_string(),    Query::order_desc("$createdAt").to_string(),    Query::limit(25).to_string(),    Query::offset(50).to_string(),];
let multi_value = Query::equal(    "status",    Value::Array(vec![        Value::String("draft".to_string()),        Value::String("published".to_string()),    ]),).to_string();

File Storage

rust
use appwrite::id::ID;use appwrite::input_file::InputFile;use appwrite::permission::Permission;use appwrite::query::Query;use appwrite::role::Role;use appwrite::services::Storage;
let storage = Storage::new(&client);
// Create bucketlet _bucket = storage    .create_bucket(        ID::unique(),        "Uploads",        Some(vec![            Permission::read(Role::any()).to_string(),            Permission::create(Role::users(None)).to_string(),        ]),        Some(true),        Some(true),        Some(30_000_000),        Some(vec!["jpg".to_string(), "png".to_string(), "pdf".to_string()]),        None,        Some(true),        Some(true),        Some(true),    )    .await?;
// Upload from disklet input = InputFile::from_path("avatar.png", Some("image/png")).await?;let _file = storage    .create_file(        "[BUCKET_ID]",        ID::unique(),        input,        Some(vec![Permission::read(Role::any()).to_string()]),    )    .await?;
// Upload from byteslet input = InputFile::from_bytes(b"hello".to_vec(), "hello.txt", Some("text/plain"));let _file = storage.create_file("[BUCKET_ID]", ID::unique(), input, None).await?;
// List fileslet _files = storage    .list_files("[BUCKET_ID]", Some(vec![Query::limit(10).to_string()]), None, Some(true))    .await?;
// Download file byteslet _content = storage    .get_file_download("[BUCKET_ID]", "[FILE_ID]", None)    .await?;
// Delete filestorage.delete_file("[BUCKET_ID]", "[FILE_ID]").await?;

Functions

rust
use appwrite::enums::ExecutionMethod;use appwrite::query::Query;use appwrite::services::Functions;use serde_json::json;
let functions = Functions::new(&client);
// List functionslet _functions = functions    .list(Some(vec![Query::limit(25).to_string()]), None, Some(true))    .await?;
// Execute functionlet _execution = functions    .create_execution(        "[FUNCTION_ID]",        Some(r#"{"hello":"world"}"#),        Some(false),        Some("/jobs/sync"),        Some(ExecutionMethod::POST),        Some(json!({ "content-type": "application/json" })),        None,    )    .await?;
// Get executionlet _execution = functions    .get_execution("[FUNCTION_ID]", "[EXECUTION_ID]")    .await?;

Permissions

rust
use appwrite::permission::Permission;use appwrite::role::Role;
let permissions = vec![    Permission::read(Role::any()).to_string(),    Permission::create(Role::users(None)).to_string(),    Permission::update(Role::user("[USER_ID]", None)).to_string(),    Permission::delete(Role::team("[TEAM_ID]", Some("owner"))).to_string(),];

Error Handling

rust
match users.get("[USER_ID]").await {    Ok(user) => {        let _user = user;    }    Err(error) if error.status_code() == 404 => {        eprintln!("User not found: {}", error.get_message());    }    Err(error) => {        eprintln!("Appwrite error {}: {}", error.status_code(), error.get_message());        return Err(Box::new(error) as Box<dyn std::error::Error>);    }}

Common Pitfalls

  • The Rust SDK is currently a server-side SDK. Prefer TypeScript/Web, Flutter, Apple, Android, or React Native SDKs for browser/mobile client auth flows.
  • Always await service calls.
  • Pass None for optional parameters you are not using.
  • Use TablesDB, not legacy Databases, for new database code.
  • Convert queries with .to_string() before passing them to APIs that expect Option<Vec<String>>.
  • Use serde_json::json!({...}) for row data and JSON bodies.
  • Use InputFile::from_path(...).await? or InputFile::from_bytes(...) for uploads.

Source and attribution

Source:appwrite/claude-plugininskills/rustat commitab3c90b

License: No license

Content belongs to its original authors. SourceWeft indexes it from a public repository.

Report or request removal

Rust Agent Skill | SourceWeft