rust-backend

Applies Windmill-specific Rust coding patterns for backend error handling, SQLx queries, and async concurrency.

Updated May 28, 2026
One-click install
npx skills add https://github.com/kma-core/windmill --skill rust-backend-kma-core
Or copy as Structured Prompt for Agent
Please help me install this Agent Skill.
Skill: rust-backend
Source: https://github.com/kma-core/windmill/tree/main/.agents/skills/rust-backend
Command: npx skills add https://github.com/kma-core/windmill --skill rust-backend-kma-core

SYSTEM DOCUMENTATION & REQUIREMENTS

What problem does it solve? Writing Rust code in the Windmill backend requires following project-specific conventions for error handling, database queries, JSON serialization, and async patterns. Without these guidelines, code may break backwards compatibility, block the async runtime, or introduce panics in library code. ## Core Features & Use Cases - Error Handling Standards: Enforces use of Error from windmill_common::error with Result<T, Error> returns, and prohibits panics in library code. - SQLx Query Patterns: Prevents SELECT * usage for backwards compatibility, promotes batch queries to avoid N+1 problems, and requires parameterized transactions. - Async & Serde Optimization: Guides correct mutex selection, spawn_blocking for CPU work, Box<RawValue> for JSON passthrough, and serde skip attributes. - Use Case: When adding a new Axum API endpoint in windmill-api/src/ that queries jobs from the database, apply these patterns to write a handler with destructured extractors, explicit column lists, and proper error propagation. ## Quick Start Apply the rust-backend guidelines to write a new Axum handler in the backend that fetches a job by ID using SQLx with explicit columns and proper error handling.

Frequently Asked Questions about rust-backend

High-intent search queries and answers about installing and using this skill.

FAQPage Schema
How do I handle errors in Rust backend code with SQLx?

Return Result<T, Error> using the Error type from windmill_common::error. Convert missing rows with ok_or_else and Error::NotFound, and propagate database errors with the ? operator instead of panicking.

Why should I avoid SELECT * in SQLx queries?

SELECT * breaks backwards compatibility when workers lag behind the API version and new columns are added. Always list columns explicitly in sqlx::query_as! so older workers continue functioning during rolling deployments.

When should I use tokio::sync::Mutex vs std::sync::Mutex?

Prefer std::sync::Mutex or parking_lot::Mutex for general data protection in async code. Only use tokio::sync::Mutex when you must hold the lock across .await points, since std mutex guards cannot be held across awaits.

How do I avoid N+1 queries with SQLx in Rust?

Use batch operations with an IN clause via WHERE id = ANY($1) passing a slice of IDs, then fetch_all in a single query. This replaces per-item queries inside loops that cause N+1 performance problems.

When should I use Box<RawValue> instead of serde_json::Value?

Use Box<serde_json::value::RawValue> when storing or passing JSON without inspecting it, since it avoids parsing overhead. Only use serde_json::Value when the code needs to read or modify the JSON contents.