Karango

A type-safe Kotlin DSL for ArangoDB queries.

If you're not using ArangoDB, this page is not for you. But if you are — well, you probably know how it feels to debug AQL strings at 2am.

String-based queries don't scale

Building database queries as strings works until the project grows. Then you rename a field in your data class and spend an hour hunting down all the query strings that still reference the old name. Typos in field names, wrong collection references, mismatched types — you only find out at runtime, usually in production.

This isn't unique to ArangoDB. SQL has the same problem, and ORMs exist for exactly this reason. Karango is the same idea for AQL: move query construction into Kotlin's type system so the compiler catches mistakes before the database does.

The Solution

@Vault
data class Person(val name: String, val age: Int)

class PersonsRepo(driver: KarangoDriver) : EntityRepository<Person>(
    name = "persons", storedType = kType(), driver = driver
)

// Type-safe query — field names are checked at compile time
val adults = repo.findList {
    FOR(repo) { person ->
        FILTER(person.name EQ "Alice")   // person.name is type-safe
        FILTER(person.age GTE 18)        // person.age is type-safe
        SORT(person.age.DESC)
        LIMIT(10)
        RETURN(person)
    }
}

Rename name to fullName in the data class? The compiler tells you every query that needs updating. Misspell a field? Red squiggle before you even run the code.

How It Works

  1. Annotate your data class with @Vault
  2. KSP generates type-safe property accessors at compile time
  3. Write queries using a Kotlin DSL that mirrors AQL syntax
  4. Karango compiles the DSL to AQL strings and executes them against ArangoDB

What You Get

Type-Safe Queries

Field names, types, and operators checked at compile time via KSP-generated accessors.

Repository Pattern

Full CRUD: insert, save, remove, find, batch insert. With lifecycle hooks and index management.

100+ AQL Functions

Math, string, array, type-check, and aggregate functions — all available in the Kotlin DSL.

Async & Coroutines

All operations are suspend functions. Streaming cursors for large result sets.

Slumber Integration

Serialization via Slumber — polymorphic types, entity references, and graceful error handling built in.

Battle-Tested

131 test files. Used in production across authentication, logging, cluster management, and more.