Skip to main content

SQLx Postgres Connection Pool

Technical Review Approved
Updated: 2026-09-13
Actix Web 4.x
RS Rust 1.75+
VERIFIED

How to properly configure a sqlx::PgPool as Application State in Actix Web.

Actix Web: 4.x
Rust: 1.75+

What You Will Build

A robust API that connects to PostgreSQL using SQLx and queries the current database time.

What You Will Learn

  • How to initialize a database connection pool asynchronously
  • How to pass a SQLx pool into Actix Web as shared state
  • Why SQLx pools do NOT need a Mutex wrapper

Project Setup

src/main.rs
1cargo new sqlx-actix
2cd sqlx-actix

Dependencies (`Cargo.toml`)

src/main.rs
1[dependencies]
2actix-web = "4"
3tokio = { version = "1", features = ["macros", "rt-multi-thread"] }
4sqlx = { version = "0.7", features = ["runtime-tokio-rustls", "postgres", "macros"] }

Complete Code

src/main.rs
1use actix_web::{web, App, HttpServer, HttpResponse, Responder};
2use sqlx::{PgPool, postgres::PgPoolOptions};
3
4// Our handler extracts the PgPool directly
5async fn get_time(pool: web::Data<PgPool>) -> impl Responder {
6 // Execute an async SQL query
7 let result: Result<(String,), sqlx::Error> = sqlx::query_as("SELECT NOW()::text")
8 .fetch_one(pool.get_ref())
9 .await;
10
11 match result {
12 Ok((time,)) => HttpResponse::Ok().body(format!("Database time: {}", time)),
13 Err(e) => HttpResponse::InternalServerError().body(e.to_string()),
14 }
15}
16
17#[actix_web::main]
18async fn main() -> std::io::Result<()> {
19 let database_url = "postgres://user:password@localhost/mydb";
20
21 // Initialize the pool asynchronously BEFORE starting Actix Web
22 let pool = PgPoolOptions::new()
23 .max_connections(5)
24 .connect(database_url)
25 .await
26 .expect("Failed to connect to Postgres");
27
28 // Wrap the pool in web::Data
29 let app_state = web::Data::new(pool);
30
31 println!("Starting server on http://127.0.0.1:8080");
32
33 HttpServer::new(move || {
34 App::new()
35 .app_data(app_state.clone()) // Share pool across threads
36 .route("/time", web::get().to(get_time))
37 })
38 .bind(("127.0.0.1", 8080))?
39 .run()
40 .await
41}
Line 22 - 27

What it does

Why use it?

How it works underneath

Expected Result

src/main.rs
1$ curl http://127.0.0.1:8080/time
2Database time: 2026-09-17 12:34:56.123456+00

How It Works

The `sqlx::PgPool` is initialized before the HTTP server starts. Because a `PgPool` internally manages its own connections and is designed to be cloned safely across threads, we wrap it directly in `web::Data<PgPool>`. Inside the handler, we call `pool.get_ref()` to yield a reference to the pool for the `fetch_one` query.


Related Documentation

Related Lessons