What Claude Code or Cursor has to write to get an Axum service with Postgres and Pub/Sub onto AWS, and how Encore lets the agent test the whole thing locally and deploy it to your own account.
Rust is a good language for an agent to write backend code in, because the compiler, through rules such as ownership, rejects whole classes of mistakes before anything runs, although that advantage stops at the edge of the binary.
When you ask an agent to deploy an Axum service with a database and a queue to AWS, the compiler has no opinion about the ECS task definition or the RDS security group, and those are the parts most likely to be wrong. In the IaC-Eval benchmark published at NeurIPS 2024, the best model tested passed under 20 percent of infrastructure-as-code tasks on the first attempt.
This guide compares the route where the agent writes that infrastructure with one where it only writes Rust.
The usual AWS layout for a Rust API is a container on ECS with Fargate behind an Application Load Balancer, with Postgres on RDS and SNS feeding SQS for events. The agent adds the AWS SDK for Rust and a Postgres client to the crate, configured from environment variables. It also writes a multi-stage Dockerfile that builds the release binary. Then it writes the infrastructure: the VPC and subnets, the ECS service with its task definition and roles, the RDS instance with its password in Secrets Manager, and the topic and queue with a queue policy and a consumer.
This gives the team complete control and works with any AWS service, and for an agent the cost is the feedback loop. A release build plus an image push plus an infrastructure apply takes minutes per attempt, and a wrong security group rule shows up as a timeout, which is a hard error for a model to reason about.
Encore combines an infrastructure SDK for your existing Rust code with a platform that provisions what that code declares, locally and in your own AWS account. The Axum app keeps its router. Resources are static declarations that Encore finds through static analysis, and the subscription is registered with an attribute:
use axum::{extract::Path, http::StatusCode, routing::post, Router};
use encore::pubsub::{Message, Subscription, Topic};
use encore::storage::postgres::Database;
use serde::{Deserialize, Serialize};
// Postgres under `encore run`, RDS in your AWS account on deploy.
static DB: Database = Database::new("users").migrations("./migrations");
#[derive(Debug, Clone, Serialize, Deserialize)]
struct UserAdded {
name: String,
}
// SNS and SQS in AWS, a local broker under `encore run`.
static USER_ADDED: Topic<UserAdded> = Topic::new("user-added");
#[encore::pubsub::register]
static WELCOME: Subscription<UserAdded> = Subscription::new(&USER_ADDED, "welcome", welcome);
async fn welcome(msg: Message<UserAdded>) -> Result<(), encore::Error> {
tracing::info!(name = %msg.data.name, "sending welcome email");
Ok(())
}
async fn add_user(Path(name): Path<String>) -> StatusCode {
if DB.execute("INSERT INTO users (name) VALUES ($1)", &[&name]).await.is_err() {
return StatusCode::INTERNAL_SERVER_ERROR;
}
match USER_ADDED.publish(&UserAdded { name }).await {
Ok(_) => StatusCode::CREATED,
Err(_) => StatusCode::INTERNAL_SERVER_ERROR,
}
}
#[tokio::main]
async fn main() {
encore::initialize();
let app = Router::new().route("/users/:name", post(add_user));
let addr = std::env::var("ENCORE_LISTEN_ADDR").unwrap_or("0.0.0.0:8080".into());
let listener = tokio::net::TcpListener::bind(addr).await.unwrap();
axum::serve(listener, app)
.with_graceful_shutdown(encore::shutdown::signal())
.await
.unwrap();
std::process::exit(encore::shutdown::drained().await.code());
}
The route syntax is for Axum 0.7. An encore.service.json next to Cargo.toml names the service and exposes its HTTP routes:
{
"name": "axum_hello_world",
"lang": "rust",
"run": { "type": "rust" },
"api": [
{ "type": "http", "prefix": "/", "name": "axum_hello_world", "expose": true }
]
}
encore run starts Postgres locally, along with the topic, then runs the binary. The agent can curl -X POST localhost:4000/users/ada and query the users table while the welcome handler logs the event, all before a deploy. If something is wrong, the error is a Rust error or a SQL error on the agent's own machine, which it can fix in the same session.
On deploy, Encore provisions the database, topics and compute in your AWS account. The AWS infrastructure reference lists every resource, and connecting the account is done once by an admin through an IAM role. From then on the agent works in Rust, and cloud access sits with Encore's IAM role, not the agent.
Capacity and networking are configured per environment outside the code, which keeps an agent's change to a diff of the crate. Each pull request can also get a preview environment with its own infrastructure, so a reviewer can call the new route before merging.
Encore covers the primitives most Rust backends need, including Postgres, Pub/Sub, object storage, cron, secrets and Redis. Crates that talk to other AWS services, such as DynamoDB, are used through the AWS SDK for Rust next to the Encore declarations.
With Encore, the agent adds the encore-dev crate to the existing Axum app, declares the database and topics as statics and adds an encore.service.json. encore run starts Postgres locally along with a local Pub/Sub broker, so the agent can call the routes and check the result, and Encore provisions the database, topics and compute in your AWS account on deploy. Without Encore, the agent writes a Dockerfile and the ECS, RDS, SNS, SQS and IAM resources in infrastructure code, then deploys to test.
No. Routing, extractors and middleware stay in Axum. Encore is an infrastructure SDK, so the app keeps its Router and adds static declarations for the resources it uses.
Release builds take time, and on top of that every infrastructure change is checked only against a real AWS account. Moving the checks to a local environment with real Postgres and Pub/Sub shortens the loop to a cargo build and a request.
Deploy to your cloud on AWS and Google Cloud
without managing infrastructure
Encore lets developers and agents define application infrastructure directly in code, then automatically provisions it from local development to production in your AWS or GCP account.