# Metadata

> Get information about the app and the environment it runs in

Encore tries to provide a cloud-agnostic environment, but sometimes it's useful to know more about where your code is running. Encore.rs exposes metadata about the application, its environment, build, and deployment through `encore::env::app_meta()`, also available as `encore::app_meta()`.

## Application metadata

`app_meta()` returns a `&'static AppMeta`. It's computed once, when the runtime is initialized, so repeated calls are free.

```rust
let md = encore::app_meta();
println!("running {} in {}", md.app_id, md.environment.name);
```

`AppMeta` has these fields:

| Field | Type | Description |
|---|---|---|
| `app_id` | `String` | The application's ID on Encore Cloud. Empty if the app isn't linked to Encore Cloud. |
| `app_slug` | `String` | The application's human-readable identifier, as shown in the Encore Cloud dashboard. Empty if the app isn't linked. |
| `gateways` | `HashMap<String, GatewayMeta>` | The API gateways that serve the application, keyed by name. |
| `environment` | `EnvironmentMeta` | The environment the app is running in. |
| `build` | `BuildMeta` | The build: `revision` is the version control revision it was built from. |
| `deploy` | `DeployMeta` | The deployment: its `id`, `deploy_time`, and `hosted_services` (the services this deployment hosts, each with a `name`). |

### Environment

`md.environment` is an `EnvironmentMeta` with:

- `name`: the environment's name. For `encore run` it's `local`, and for `encore test` it's `test`.
- `r#type`: an `EnvironmentType`, one of `Production`, `Development`, `Ephemeral` (such as preview environments), or `Test`. `encore run` reports `Development`.
- `cloud`: a `CloudProvider`, one of `AWS`, `GCP`, `Azure`, `Encore`, or `Local`. Locally it's `Local`.

These enums don't implement `PartialEq`, so compare them with `matches!` or a `match`:

```rust
use encore::env::EnvironmentType;

let is_prod = matches!(encore::app_meta().environment.r#type, EnvironmentType::Production);
```

### Gateways

An app can have several gateways, so there's no single base URL. Look up the one you mean by name; each `GatewayMeta` has a `name` and a `base_url`:

```rust
if let Some(gw) = encore::app_meta().gateway("api") {
    println!("api is served at {}", gw.base_url);
}
```

A process that no gateway serves, such as a worker, has an empty `gateways` map.

## Example use cases

### Using cloud-specific services

Encore doesn't natively support every service each cloud offers. Using the environment's cloud provider, you can choose an implementation per cloud. For example, to write audit logs to a data warehouse:

```rust
use encore::env::CloudProvider;

async fn audit(action: &str, user_id: &str) -> Result<(), AuditError> {
    match encore::app_meta().environment.cloud {
        CloudProvider::AWS => write_to_redshift(action, user_id).await,
        CloudProvider::GCP => write_to_bigquery(action, user_id).await,
        CloudProvider::Local => write_to_file(action, user_id).await,
        CloudProvider::Azure | CloudProvider::Encore => Err(AuditError::Unsupported),
    }
}
```

### Checking the environment type

When building a signup flow, you may want to skip email verification during development and in tests:

```rust
use encore::env::EnvironmentType;

async fn finish_signup(user_id: &str) -> Result<(), SignupError> {
    match encore::app_meta().environment.r#type {
        EnvironmentType::Development | EnvironmentType::Test => {
            mark_email_verified(user_id).await
        }
        _ => send_verification_email(user_id).await,
    }
}
```

For values that differ per environment, consider [configuration](/docs/rs/develop/config) instead: overlay files per environment type or environment name keep the differences out of your code.
