Skip to content
Quick start

Your first app

Start a small writing app by creating Maya's account. You'll define a User model, generate its Rust client, create the database, and save and read back your first user. Later tutorials add Maya's posts and conversations with Ken, one capability at a time.

This walkthrough uses SQLite so you can get running without setting up a database server. The same schema and client workflow applies to PostgreSQL, MySQL, and MariaDB.

Before you begin

Follow installation to set up Rust and the Rent CLI. Rent is available through private preview.

Create an application

Create a new SQLite application:

rent new social-app --database sqlite
cd social-app

rent new creates a two-crate workspace: social-app, where your code goes, and social-app-db, which owns the starter User entity, the generated client, and the migration directory. It also writes rent.toml, formatter settings, a local .env containing DATABASE_URL, and a dependency pinned to the installed CLI's Rent revision. Rent loads that project .env automatically. Keeping the client in its own crate means an edit to your code never recompiles the generated client.

Check the complete project before changing the database:

rent doctor
Rent Doctor

Ready Configuration  ./rent.toml
Ready Cargo project
Ready Schema         1 entity
Ready Client         generated and current
Ready Module         declared in the crate root
Ready Layout         generated client in its own crate, social-app-db
Ready Migrations     no migration history yet
Ready Database       sqlite connection verified

Healthy: Rent project is healthy.

Create the database schema

Turn the starter RSL model into the first migration and apply it:

rent migrate dev --name initial

migrate dev performs a complete local feedback loop. It inspects the database, plans the difference, writes a checksummed SQL migration, applies pending migrations, and inspects again to prove the database now matches the RSL schema.

Migration: initial

Created ./social-app-db/rent/migrations/20260910023750_initial.sql (1 change)
Applied 20260910023750_initial (1 statement)
Verified: Database matches the RSL schema.

Compile and run the generated application:

cargo check
cargo run
Rent connected

At this point the complete path works: RSL schema → generated Rust client → reviewed migration → live database → async application.

Understand the generated project

The files you will work with most often are:

PathWhat it doesHow to treat it
rent.tomlConfigures the schema, generated code, migration, and extension manifest paths and the development databaseEdit and commit
social-app-db/rent/schema.rslDefines models, fields, relationships, indexes, and database objectsEdit and commit
social-app-db/rent/generated/Contains schema-specific models and client builders, declared in social-app-db/src/lib.rsRegenerate and commit. Do not hand-edit
social-app-db/rent/migrations/*.sqlStores append-only schema and authored data migrationsReview and commit
social-app-db/rent/migrations/rent.sumProtects migration history with checksumsUpdate through Rent commands and commit
social-app/src/main.rsConnects the generated client to application codeEdit as ordinary Rust

Code generation and migration planning both read the same social-app-db/rent/schema.rsl source of truth.

Make your first schema change

Open social-app-db/rent/schema.rsl and expand the starter model:

model User {
  id      BigInt @id @default(autoincrement())
  email   String @unique
  name    String
  version UInt   @rent.version

}

Inspect Rent's interpretation, rebuild the client, and migrate the development database:

rent describe
rent generate
rent migrate preflight
rent migrate dev --name add_user_profile

Use rent dev in another terminal when you want generation to follow schema edits automatically.

Use the typed client

The generated client accepts borrowed strings and exposes methods derived from the schema:

let maya = client
    .create_user()
    .email("maya@example.com")
    .name("Maya")
    .save()
    .await?;

let same_user = client
    .user()
    .email_eq("maya@example.com")
    .only()
    .await?;

only() returns one row or a typed cardinality error. Use only_or_none(), all(), count(), projections, pages, or bounded streams when the expected result shape differs.

The generated application connects from DATABASE_URL:

let database_url = std::env::var("DATABASE_URL")?;

let client = generated::client::Client::connect(&database_url).await?;

Use Client::connect_with when the application needs custom pool limits, acquisition timeouts, or connection lifetime settings.

Browse the result

Open the development database in Rent Studio:

rent studio

Studio opens a loopback-only web interface and is read-only by default. Press Ctrl+C in its terminal to stop it.

Your everyday loop

Once the project is established, most schema work follows this sequence:

rent describe
rent generate
rent migrate preflight
rent migrate dev --name describe_the_change
cargo nextest run

Use rent doctor whenever configuration, generated code, migrations, Cargo features, or database connectivity seem inconsistent.

Choose what to learn next

You now have a running application. Continue building with the step-by-step tutorials, or choose a guide for a particular task.

Before shipping, work through application testing, then production deployment.