---
sidebar_label: Overview
toc_max_heading_level: 3
doc_id: 27b7688a-d4c4-4e26-b815-4b47594db491
description: >-
  Parameters let you configure app runtime behavior via environment variables or
  files with specific limitations.
keywords:
  - parameters
  - environment variables
  - configuration
  - runtime behavior
  - file delivery
---

# Parameters

Parameters let you pass configuration to your application at runtime.

Some typical use cases include:

- Change behavior based on scope (e.g., region, read vs. write)
- Provide the application slug or identifier to fetch configuration
- Load application-specific values (e.g., blocked users)
- Configure third-party software (e.g., configuration files)

## How parameters work

### Environment variables vs. files

Parameters can be delivered as **environment variables** or **files** (server-based scopes only).

Files can be delivered to any directory you choose; by default, they are placed in the `/app-data/` directory.

Environment variables are limited to 4 KB, while files can be up to 1 MB.


### File support limitations

While parameters can be delivered as **files**, only text-based files are supported. Binary formats such as PDFs or images may not work correctly due to internal processing.

Specifically:

- Uploaded files are not delivered "as-is". They are **processed as UTF-8 encoded text**.
- This means binary formats like PDFs may get corrupted or become unusable by the application.

If you’re unsure whether a file format is supported, try opening it in a UTF-8 text editor. If it’s unreadable, it’s not a good candidate for file parameters.

#### Using PDFs as parameters

The parameter system is not designed for binary files like PDFs. Attempting to upload one may cause encoding issues that corrupt the content.

##### Recommended workaround

**Upload the PDF to object storage** (e.g., S3) and pass its URL as a parameter. This lets your application fetch the file at runtime without encoding issues.

Example:

```yaml
destination_path: "https://my-bucket.s3.amazonaws.com/help-doc.pdf"

```
> **Note:** See the [Parameters API docs](/docs/api/parameter-create) for more information.


### Parameter levels: application, dimension, and scope

In nullplatform, parameters can be set at the application level, the scope level, or by using dimensions. This means you can:

- Set a value for the whole application
- Override it for specific scopes
- Group scopes using shared dimensions and apply values to all of them

Here’s an example comparing application-level and scope-level parameters:
  
```mermaid
graph TD
    app[<b>Application</b><br>Advertising API] --> app_param([DB_HOSTNAME=global.mydb.mycloud.com])
    app --- scope_us
    app --- scope_europe
    app --- scope_rotw
    scope_rotw -. Uses application level value .-> app_param
    scope_us(<b>Scope</b><br>US) --> app_param_us([DB_HOSTNAME=us.mydb.mycloud.com])
    scope_europe(<b>Scope</b><br>Europe) --> app_param_us([DB_HOSTNAME=us.mydb.mycloud.com])
    scope_rotw(<b>Scope</b><br>Rest of<br>the World)
```

Let’s now consider this topology:


```mermaid
graph TD
    app[<b>Application</b><br>Advertising API]
    scope_production_us(<b>Scope</b><br>Production<br>US)
    scope_development_us(<b>Scope</b><br>Development<br>US)
    scope_development_europe(<b>Scope</b><br>Development<br>Europe)
    scope_development_latam(<b>Scope</b><br>Development<br>Latam)
    app --> scope_production_us
    app --> scope_development_us
    app --> scope_development_europe
    app --> scope_development_latam
```


We have four scopes. Three are `development` environments, and one is a `production` environment.

With only application-level and scope-level parameters, we can:

- Set a value at the `application level`, which affects all scopes
- Set a value at the `scope level`, which affects only that scope

But what if you want to set the same value for all development environments (multiple scopes at once)? That’s where **dimensions** come into play.

By assigning a dimension like `environment=development`, the parameter applies to all scopes that share that dimension:

```mermaid
graph TD
    dimension(Dimension<br>environment = development)
    app[<b>Application</b><br>Advertising API]
    scope_production_us(<b>Scope</b><br>Production<br>US)
    scope_development_us(<b>Scope</b><br>Development<br>US)
    scope_development_europe(<b>Scope</b><br>Development<br>Europe)
    scope_development_latam(<b>Scope</b><br>Development<br>LATAM)
    development_param([DB_HOSTNAME=dev.mydb.mycloud.com])
    app --> scope_production_us
    app --> scope_development_us
    app --> scope_development_europe
    app --> scope_development_latam
    scope_development_us .-> development_param
    scope_development_europe .-> development_param
    scope_development_latam .-> development_param
    class dimension title;
    classDef title stroke: none, fill: transparent;
```

Another example: if you want to apply a parameter only to services deployed in the US, you can use the dimension `country=us`. This value applies to all scopes with that dimension.

> **Note:** In this case, you're applying the same parameter value to multiple scopes. For all other scopes, you can use another dimension or set values at the application or scope level.

```mermaid
graph TD
    dimension_us(Dimension<br>country = us)
    app[<b>Application</b><br>Advertising API]
    scope_production_us(<b>Scope</b><br>Production<br>US)
    scope_development_us(<b>Scope</b><br>Development<br>US)
    scope_development_europe(<b>Scope</b><br>Development<br>Europe)
    scope_development_latam(<b>Scope</b><br>Development<br>LATAM)
    param([LOG_LEVEL=debug])
    app --> scope_production_us
    app --> scope_development_us
    app --> scope_development_europe
    app --> scope_development_latam
    scope_production_us .-> param
    scope_development_us .-> param
    class dimension_us dimension;
    classDef dimension fill: none, stroke: none;
```

### Order of precedence

You can define parameter values at three levels:

- **Application** – the broadest level, applies to all scopes
- **Dimension** – an intermediate level that applies to scopes with matching dimension values
- **Scope** – the most specific level, overrides all others

The **order of precedence** is:

1. Scope
2. Dimension
3. Application

If a parameter is set at multiple levels, the **most specific** one is applied.

Example:

- `TIMEOUT` is defined as:
  - `1000` for the dimension `environment=development`
  - `2000` for the scope `development_us`

Then:

- A deployment in `development_us` gets `2000`
- A deployment in another `development` scope gets `1000`


### Secrets

If you want to store sensitive information (e.g., database passwords), mark the parameter as **secret**.

- Secret parameters can be overwritten
- Reading secret values requires specific permissions  

> **Note:** See [Accessing secret values](/docs/parameters/secret-visibility) for more information.


### Read-only parameters

Certain roles can create **read-only parameters**, which can only be modified by roles with specific permissions.


## How parameters are applied

To keep environments predictable, we favor immutability: **parameters are not hot-reloaded**. Any change to parameter values requires a new deployment.

If you roll back a deployment, we automatically restore the parameter values that were present at the time of that deployment, ensuring safe and consistent rollbacks.

### Versioning

Parameter values are **versioned**. Every time you change the value of a parameter, a new version is created.

### Previous versions & rollbacks

- You can **query old versions** of parameters
- You can **roll back to a previous version**, which creates a **new version** with the previous values
- You can also start from a previous version and apply new changes on top

### Packing changes

Just like committing multiple files in Git, you can **batch multiple changes** into a single new parameter version.

Example lifecycle:

```mermaid
flowchart TD
    create["NEW Parameter POOL_SIZE <br> <b>Version = null</b>"]
    add_v1["SET Value 100 for Scope 1 <br> <b>Version = 1</b>"]
    add_v2["SET Value 80 for Scope 2 <br> <b>Version = 2</b>"]
    add_v3["SET Value 120 for Scope 1 <br> SET Value 90 for Scope 2 <br> <b>Version = 3</b>"]
    restore["RESTORE Version 1 <br> SET Value 85 for Scope 2 <br> <b>Version = 4</b>"]
    create --> add_v1 --> add_v2 --> add_v3 --> restore

```

:::note Some things to note here:

- A new parameter has no version until values are added.
- You can apply multiple updates in one commit to create a single version.
:::

## API and CLI

All parameter operations can be performed through the **API** or the **CLI**, depending on your preferred workflow.

You can use them to:

- Create, update, or delete parameters
- Retrieve current values or past versions
- Roll back to previous versions
- Apply values at application, scope, or dimension level
- Mark parameters as secrets or read-only

> **Note:** See the [API reference](/docs/parameters-api-index) for API and CLI details and usage examples.

## Next steps

- [Accessing secret values](/docs/parameters/secret-visibility): how to read masked values when authorized.
- [Storage backends](/docs/parameters/storage): keep parameter values in a system you control instead of nullplatform's database.
- [Injected environment variables](/docs/parameters/injected-parameters): variables nullplatform sets automatically at runtime.
