# Connecting a Database

Our app needs a way to store secrets before it can send them to another requester. We could store everything in a shared state memory, but when the thruster server shutdown we'd lose everything, and it would be hard to scale to more than one instance reasonably (*ain't nobody got time to implement Paxos.*)

So we need a database! For this example, we'll be using Postgres along with sqlx. Postgres is a pretty standard choice, but why sqlx as our rust library? Well, it's quick to set up and has a nice compile time query checker if you have a database running locally.

Start by making a new `schema.sql` file in the root folder.

```sql
CREATE TABLE IF NOT EXISTS secrets (
    secret_id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
    encoded_secret VARCHAR(1024) NOT NULL,
    salt VARCHAR(22) NOT NULL,
    created_at TIMESTAMPTZ DEFAULT now(),
    expires_at TIMESTAMPTZ
);
```

{% hint style="info" %}
*If we were making a more "production" ready app, of course we'd want to use proper migrations rather than a single "schema" file.* [*diesel*](https://diesel.rs/) *is a great tool for running migrations. It even has a proper ORM if you want the extra safety around your data model!*
{% endhint %}

We'll need to run this migration when the app starts (note that we only create the table if it doesn't already exist -- so the app can be run multiple times without clearing the data out of the table or failing because of conflicts!)

Add the following to your `Cargo.toml` under the "dependencies" section:

```toml
sqlx = { version = "0.6", features = ["runtime-tokio-native-tls", "postgres"] }
```

Now we need to actually apply the schema when our app runs. Make your `main` function look like this:

```rust
#[tokio::main]
async fn main() {
    env_logger::init();
    info!("Starting server...");

    let pool = PgPoolOptions::new()
        .max_connections(5)
        .connect("postgres://postgres:password@localhost/pigeon")
        .await
        .expect("Could not create postgres connection pool");

    pool.execute(include_str!("../schema.sql"))
        .await
        .expect("Could not create schema in database");

    let app = App::<HyperRequest, Ctx, ServerConfig>::create(generate_context, ServerConfig {})
        .get("/hello", m![hello]);

    let server = HyperServer::new(app);
    server.build("0.0.0.0", 4321).await;
}
```

You'll note that we add a pool, execute the schema on the pool (i.e. we run the above sql code,) and then we... don't really do anything with the pool -- yet!

Before we try running this, we'll need to, you know, actually have a postgres instance running locally! Docker is a great way to do this without much fuss. If you don't already have Docker installed, do so now, then run

```bash
docker run -d \
    -e POSTGRES_PASSWORD=password \
    -e POSTGRES_DB=pigeon \
    -p 5432:5432
    --name=pigeon-dev \
    postgres
```

This starts postgres in a container and detaches it, letting you run the program,

```
cargo run
```

Which should run nice an easy! You did it, you connected to a database!!
