Профессиональная разработка бэкенда на Rust (Axum) под ключ

Мы часто сталкиваемся с ситуацией: проект растёт, нагрузка увеличивается, а Node.js или Python начинают «тормозить». Rust — не панацея, но там где важна предсказуемая производительность и надёжность, он выигрывает. По нашим бенчмаркам, Rust-бэкенд на Axum обрабатывает до 100 000 запросов в секунду н

Разработка и обслуживание любых видов сайтов:

Информационные сайты или веб-приложения
Сайты визитки, landing page, корпоративные сайты, онлайн каталоги, квиз, промо-сайты, блоги, новостные ресурсы, информационные порталы, форумы, агрегаторы
Сайты или веб-приложения электронной коммерции
Интернет-магазины, B2B-порталы, маркетплейсы, онлайн-обменники, кэшбэк-сайты, биржи, дропшиппинг-платформы, парсеры товаров
Веб-приложения для управления бизнес-процессами
CRM-системы, ERP-системы, корпоративные порталы, системы управления производством, парсеры информации
Сайты или веб-приложения электронных услуг
Доски объявлений, онлайн-школы, онлайн-кинотеатры, конструкторы сайтов, порталы предоставления электронных услуг, видеохостинги, тематические порталы

Это лишь некоторые из технических типов сайтов, с которыми мы работаем, и каждый из них может иметь свои специфические особенности и функциональность, а также быть адаптированным под конкретные потребности и цели клиента

Услуги, которые мы предлагаем
Показано 1 из 1Все 2062 услуг
Профессиональная разработка бэкенда на Rust (Axum) под ключ
Сложный
от 2 недель до 3 месяцев

Наши компетенции:

Часто задаваемые вопросы

Последние работы

  • image_website-b2b-advance_0.webp
    Разработка сайта компании B2B ADVANCE
    1414
  • image_web-applications_feedme_466_0.webp
    Разработка веб-приложения для компании FEEDME
    1285
  • image_websites_belfingroup_462_0.webp
    Разработка веб-сайта для компании БЕЛФИНГРУПП
    982
  • image_ecommerce_furnoro_435_0.webp
    Разработка интернет магазина для компании FURNORO
    1241
  • image_crm_enviok_479_0.webp
    Разработка веб-приложения для компании Enviok
    982
  • image_bitrix-bitrix-24-1c_fixper_448_0.webp
    Разработка веб-сайта для компании ФИКСПЕР
    994

Мы часто сталкиваемся с ситуацией: проект растёт, нагрузка увеличивается, а Node.js или Python начинают «тормозить». Rust — не панацея, но там где важна предсказуемая производительность и надёжность, он выигрывает. По нашим бенчмаркам, Rust-бэкенд на Axum обрабатывает до 100 000 запросов в секунду на одном ядре, потребляя в 2–3 раза меньше памяти, чем аналогичное решение на Node.js. Axum — HTTP-фреймворк из экосистемы Tokio, созданный командой Tokio. Его отличие от Actix Web — архитектурная близость к Tower middleware stack и более идиоматичный async Rust. Извлечение из запроса типизировано на уровне системы типов: если компилятор пропустил — запрос валиден. Если не пропустил — ошибка в коде, а не в рантайме. Переход на Rust позволяет сократить затраты на инфраструктуру за счёт снижения потребления ресурсов до 40%. Стоимость разработки окупается за счёт уменьшения количества инцидентов в production и снижения требований к желе. Для сложных проектов мы рекомендуем Rust Axum как основу для высоконагруженных систем.

Почему Axum, а не Actix Web?

Actix работает на собственном акторном рантайме (исторически). Axum — поверх Tokio напрямую, что упрощает интеграцию с остальными crates экосистемы: tower, tower-http, tracing. Нет отдельного треда для каждого воркера — всё в одном Tokio-рантайме. Это удобно при написании тестов и при совместном использовании с gRPC через tonic. Кроме того, Axum использует более простую модель middleware, что ускоряет разработку. В наших нагрузочных тестах Axum показывает пропускную способность на 20–30% выше, чем Actix Web, при аналогичных сценариях. Согласно официальной документации Axum, фреймворк наследует принципы Tower и Tokio, что обеспечивает бесшовную интеграцию с другими компонентами экосистемы.

Критерий Axum Actix Web
Рантайм Tokio собственный акторный
Middleware Tower (унифицировано) свой трейт
Type-safe экстракторы да частично
Простота тестирования высокая (ServiceExt) средняя
Интеграция с gRPC через tonic требуется адаптация
Этап Примерная длительность
Проектирование и архитектура 3–5 дней
Реализация CRUD (8–12 ресурсов) 5–7 дней
Аутентификация и middleware 2–3 дня
Тестирование и отладка 3–5 дней
Документация и деплой 2–3 дня

Как мы строим бэкенд на Axum под ключ?

Мы разрабатываем бэкенд целиком: от проектирования БД до деплоя. Используем актуальную версию Axum (0.8), Tokio (1.35) и sqlx (0.8). В проекте обязательно применяем:

  • sqlx для асинхронной работы с PostgreSQL (или MySQL)
  • tower-http для CORS, сжатия, трассировки
  • jsonwebtoken для JWT-аутентификации
  • serde для сериализации
  • tokio как единый рантайм

Ниже — базовая структура приложения, которую мы берём за основу.

// main.rs use axum::{routing::{get, post}, Router}; use sqlx::PgPool; use std::sync::Arc; use tower_http::{cors::CorsLayer, trace::TraceLayer, compression::CompressionLayer}; mod config; mod errors; mod handlers; mod models; mod middleware; #[derive(Clone)] pub struct AppState { pub db: PgPool, pub config: Arc<config::Config>, } #[tokio::main] async fn main() { tracing_subscriber::fmt() .with_env_filter(std::env::var("RUST_LOG").unwrap_or_else(|_| "info".into())) .init(); let cfg = Arc::new(config::Config::from_env()); let pool = PgPool::connect(&cfg.database_url).await.unwrap(); sqlx::migrate!().run(&pool).await.unwrap(); let state = AppState { db: pool, config: cfg }; let app = Router::new() .nest("/api/v1", api_routes()) .with_state(state) .layer(TraceLayer::new_for_http()) .layer(CompressionLayer::new()) .layer(CorsLayer::permissive()); let listener = tokio::net::TcpListener::bind("0.0.0.0:3000").await.unwrap(); tracing::info!("listening on {}", listener.local_addr().unwrap()); axum::serve(listener, app).await.unwrap(); } fn api_routes() -> Router<AppState> { Router::new() .nest("/users", handlers::users::router()) .nest("/products", handlers::products::router()) } 

Экстракторы — ключевая концепция Axum

Экстракторы позволяют типизированно извлекать данные из запроса: параметры пути, query string, JSON-тело, состояние приложения. Они реализуют трейт FromRequestParts или FromRequest.

// handlers/users.rs use axum::{ extract::{Path, Query, State}, http::StatusCode, response::IntoResponse, routing::{get, post, put}, Json, Router, }; use serde::{Deserialize, Serialize}; use uuid::Uuid; use crate::{errors::AppError, models::User, AppState}; pub fn router() -> Router<AppState> { Router::new() .route("/", get(list_users).post(create_user)) .route("/:id", get(get_user).put(update_user).delete(delete_user)) } #[derive(Deserialize)] pub struct ListParams { pub page: Option<u32>, pub per_page: Option<u32>, pub search: Option<String>, } async fn list_users( State(state): State<AppState>, Query(params): Query<ListParams>, ) -> Result<impl IntoResponse, AppError> { let page = params.page.unwrap_or(1).max(1); let per_page = params.per_page.unwrap_or(25).min(100); let offset = (page - 1) * per_page; let users = sqlx::query_as!( User, r#" SELECT * FROM users WHERE ($1::text IS NULL OR email ILIKE '%' || $1 || '%') ORDER BY created_at DESC LIMIT $2 OFFSET $3 "#, params.search, per_page as i64, offset as i64 ) .fetch_all(&state.db) .await?; Ok(Json(users)) } async fn get_user( State(state): State<AppState>, Path(id): Path<Uuid>, ) -> Result<impl IntoResponse, AppError> { let user = sqlx::query_as!(User, "SELECT * FROM users WHERE id = $1", id) .fetch_optional(&state.db) .await? .ok_or_else(|| AppError::not_found("user not found"))?; Ok(Json(user)) } #[derive(Deserialize)] pub struct CreateUserPayload { pub email: String, pub name: String, pub password: String, } async fn create_user( State(state): State<AppState>, Json(payload): Json<CreateUserPayload>, ) -> Result<impl IntoResponse, AppError> { // валидация if payload.email.is_empty() || !payload.email.contains('@') { return Err(AppError::validation("invalid email")); } let hash = tokio::task::spawn_blocking(move || { bcrypt::hash(&payload.password, bcrypt::DEFAULT_COST) }) .await .unwrap() .map_err(|_| AppError::internal("hash failed"))?; let user = sqlx::query_as!( User, r#" INSERT INTO users (id, email, name, password_hash) VALUES ($1, $2, $3, $4) RETURNING * "#, Uuid::new_v4(), payload.email, payload.name, hash ) .fetch_one(&state.db) .await?; Ok((StatusCode::CREATED, Json(user))) } 

Tower middleware

Middleware-прослойки реализуются как функции, принимающие запрос и Next. Пример аутентификации через JWT:

// middleware/auth.rs use axum::{ extract::Request, http::header::AUTHORIZATION, middleware::Next, response::Response, }; use jsonwebtoken::{decode, DecodingKey, Validation}; use crate::{errors::AppError, models::Claims}; pub async fn require_auth( mut req: Request, next: Next, ) -> Result<Response, AppError> { let token = req .headers() .get(AUTHORIZATION) .and_then(|v| v.to_str().ok()) .and_then(|v| v.strip_prefix("Bearer ")) .ok_or(AppError::unauthorized())?; let secret = std::env::var("JWT_SECRET").unwrap(); let claims = decode::<Claims>( token, &DecodingKey::from_secret(secret.as_bytes()), &Validation::default(), ) .map_err(|_| AppError::unauthorized())? .claims; req.extensions_mut().insert(claims); Ok(next.run(req).await) } // в api_routes() fn api_routes() -> Router<AppState> { let protected = Router::new() .nest("/orders", handlers::orders::router()) .route_layer(middleware::from_fn(middleware::auth::require_auth)); Router::new() .nest("/auth", handlers::auth::router()) .merge(protected) } 

Когда стоит выбрать Axum вместо других фреймворков?

Axum — оптимальный выбор, если ваш проект использует асинхронный стек Tokio и требует бесшовной интеграции с Tower middleware, gRPC через tonic или WebSockets. Если же вам нужна проверенная временем стабильность или вы мигрируете с Actix, стоит взвесить: Axum имеет более простую модель middleware и легче тестируется. В наших проектах Axum показал на 20–30% более высокую пропускную способность по сравнению с Actix Web при одинаковых сценариях.

Как тестировать Axum-приложение без запуска сервера?

Axum позволяет тестировать эндпоинты напрямую через tower::ServiceExt::oneshot, не поднимая реальный порт. Это экономит время и изолирует тесты.

#[cfg(test)] mod tests { use axum::body::Body; use axum::http::{Request, StatusCode}; use tower::ServiceExt; #[tokio::test] async fn test_get_user_not_found() { let app = create_test_app().await; let response = app .oneshot( Request::builder() .uri("/api/v1/users/00000000-0000-0000-0000-000000000000") .body(Body::empty()) .unwrap(), ) .await .unwrap(); assert_eq!(response.status(), StatusCode::NOT_FOUND); } } 

Как обеспечить типобезопасность на уровне API?

Типобезопасность в Axum достигается за счет использования типизированных экстракторов — параметры запроса, JSON-тело и состояние приложения проверяются компилятором. Это значит, что ошибки несоответствия типов отлавливаются на этапе компиляции, а не в production. Дополнительно мы применяем serde для строгой валидации структур и utoipa для генерации OpenAPI-спецификации, что позволяет автоматически документировать API и проверять его контракты.

Стриминг ответов

Axum поддерживает Server-Sent Events и простые стримы через Sse:

use axum::response::sse::{Event, Sse}; use futures_util::stream; use tokio_stream::StreamExt; async fn stream_events( State(state): State<AppState>, ) -> Sse<impl futures_util::Stream<Item = Result<Event, axum::Error>>> { let stream = stream::iter(0..) .throttle(std::time::Duration::from_secs(1)) .map(|i| { Ok(Event::default() .data(format!("event #{i}")) .event("tick")) }); Sse::new(stream).keep_alive( axum::response::sse::KeepAlive::new() .interval(std::time::Duration::from_secs(15)) ) } 

Типичные ошибки новичков

  • Забывают внедрить CompressionLayer — ответы не сжимаются, TTFB растёт.
  • Используют unwrap() в production-коде — лучше обрабатывать ошибки через AppError.
  • Не настраивают пул соединений — при пиковых нагрузках теряются запросы.

Что входит в работу

  • Архитектура проекта: модули, структуры данных, middleware.
  • Реализация REST API: типизированные маршруты, экстракторы, обработка ошибок.
  • Работа с БД: миграции, запросы через sqlx, пул соединений.
  • Аутентификация и авторизация: JWT, ролевая модель.
  • Middleware: CORS, логгирование, сжатие, защита.
  • Тесты: unit-тесты для хендлеров, интеграционные тесты.
  • Документация: OpenAPI (через utoipa или вручную), README.
  • Деплой: Docker-образ, CI/CD (GitHub Actions), настройка Nginx.

Этапы разработки

  1. Анализ и проектирование: спецификация API, выбор стека, схемы БД.
  2. Создание скелета: настройка проекта, базовые модули, миграции.
  3. Разработка маршрутов: CRUD для каждой сущности, валидация.
  4. Интеграция и тестирование: написание тестов, нагрузочное тестирование.
  5. Документация и деплой: подготовка к production, мониторинг.

Сроки и стоимость

Ориентировочные сроки (зависит от сложности):

  • REST API средней сложности (8–12 ресурсов, JWT, PostgreSQL, базовые тесты): 2–3 недели.
  • Добавление WebSocket, SSE, интеграция с внешними сервисами: +1–2 недели.
  • Первый проект на Rust без опыта команды может потребовать на 30–50% больше времени.

Стоимость рассчитывается индивидуально после брифа. Для точного расчета свяжитесь с нами — мы подготовим индивидуальное предложение. Обращайтесь — обсудим ваш проект. Закажите разработку бэкенда на Rust прямо сейчас.

Официальная документация Axum: github.com/tokio-rs/axum