# KV Store quickstart

This guide instructs you through storing and reading your first key in [KV Store](/en/documentation/platform/kv-store/). By the end you will have:

- Your first namespace, created through the Azion API.
- A function that opens the namespace, writes one key, and reads it back.
- A function instance and a Rules Engine rule that run that function.
- A URI on your own application that answers with the stored value.

The **namespace** is the container KV Store keeps keys and values in, and it is permanent: it cannot be renamed, emptied, or deleted afterwards, so the name is worth choosing before the first request. The **function** holds the code that opens the namespace and calls the client. The **function instance** binds the function to an application, and the **Rules Engine** rule selects that instance and sets which requests run it. Creating a function does not execute it, and an instance without a rule never runs.

---

Select the interface you will use. The prerequisites and every stage below follow that choice.

## Prerequisites

- An Azion account. To create one, refer to [How to create an account on Azion](/en/documentation/fundamentals/creating-account/).
- KV Store Preview access on the account. The product is in Preview, and access is requested through the technical support team. To request it, refer to [Technical Support](/en/documentation/support/).
- The **Edit Functions** and **Edit Applications** permissions on the account. They grant permission to create the function and to change the application that runs it. For more information, refer to [Teams Permissions](/en/documentation/fundamentals/teams-permissions/).
- An application. To create one, refer to [Applications quickstart](/en/documentation/platform/applications/quickstart/).
- A [personal token](/en/documentation/guides/platform/account-and-billing/personal-tokens/) and `curl`. You create the namespace through the Azion API whichever interface you pick, and the request sends the token in the `Authorization` header.

**Console**

- Access to Azion Console. To sign in, refer to [Access Azion Console](/en/documentation/guides/platform/account-and-billing/how-to-access-azion-console/).

**CLI**

- The [Azion CLI](/en/documentation/devtools/cli/) installed and authorized.

**API**

- Nothing beyond the personal token and `curl` above.

---

## Create a namespace

A namespace is created through the Azion API, because KV Store has no screen in Azion Console and no Azion CLI command. Every reader follows this one procedure, whichever interface the later stages use.

The name runs 3 to 63 characters, and uses letters, numbers, the hyphen, and the underscore. Names are case-sensitive, and nothing removes a namespace once it exists, so a name created in the wrong case is permanent.

1. **Send the create request**

   Replace `[TOKEN VALUE]` with your personal token, and `my-namespace` with a name of your own:

   ```bash
   curl --request POST \
     --url https://api.azion.com/v4/workspace/kv/namespaces \
     --header 'Accept: application/json' \
     --header 'Authorization: Token [TOKEN VALUE]' \
     --header 'Content-Type: application/json' \
     --data '{
     "name": "my-namespace"
   }'
   ```

2. **Read the response**

   A `201` carries the whole namespace:

   ```json
   {
     "name": "my-namespace",
     "created_at": "2026-01-01T12:14:07.563343",
     "last_modified": "2026-01-01T12:14:07.563343"
   }
   ```

   A `400` with the message `Namespace already exists` means the account already holds that name. Choose a different name and send the request again.

The request is synchronous, and there is no provisioning state to poll. The `name` the response carries is the handle every later call uses, including the function you write next. For every field, operation, and error on this endpoint, refer to [Namespaces](/en/documentation/platform/kv-store/namespaces/).

---

## Create the function

`Azion.KV` is a global of Azion Runtime, so a [function](/en/documentation/platform/functions/) reaches it with no import line and no credential. The function below opens the namespace, writes one key, reads it back, and returns the value.

> **Caution**
>
> A call to `Azion.KV.open()` can answer `NotFound: KV namespace "my-namespace" does not exist` for a namespace that exists and that the Azion API lists. This can happen on an account with KV Store Preview access. If your function returns that error, contact the [Technical Support](/en/documentation/support/) team with the namespace name and the account it belongs to.

**Console**

To create the function in Azion Console:

1. **Open the Functions page**

   Access [Azion Console](https://console.azion.com/) > **Products Menu** > **Libraries** > **Functions**.

2. **Select + Function**

3. **Name the function**

   Enter a name for the function. For example: `kv-quickstart`.

4. **Paste the code in the Code tab**

   In the **Code** tab, paste the following code, with the name of the namespace you created:

   ```javascript
   export default {
     async fetch(request, env, ctx) {
       const kv = await Azion.KV.open('my-namespace');

       await kv.put('user-42', 'active');
       const value = await kv.get('user-42', 'text');

       return new Response(value ?? 'No value for that key');
     },
   };
   ```

5. **Select Save**

The function is saved and holds the code that reaches the namespace.

**CLI**

The CLI reads the code from a local file. To create the function:

1. **Save the code to a file**

   Write the following to `kv-quickstart.js`, with the name of the namespace you created:

   ```javascript
   export default {
     async fetch(request, env, ctx) {
       const kv = await Azion.KV.open('my-namespace');

       await kv.put('user-42', 'active');
       const value = await kv.get('user-42', 'text');

       return new Response(value ?? 'No value for that key');
     },
   };
   ```

2. **Run the create command**

   ```bash
   azion create function --name kv-quickstart --code ./kv-quickstart.js --active true
   ```

3. **Read the output**

   The command prints the id of the new function:

   ```text
   Created function with ID 12346
   ```

Record the id. The instance references the function by it.

**API**

The request body carries the code as a JSON string. The code holds single quotes, so the body is sent from a file.

1. **Write the request body to a file**

   Save the following as `function.json`, with the name of the namespace you created:

   ```json
   {
     "name": "kv-quickstart",
     "code": "export default {\n  async fetch(request, env, ctx) {\n    const kv = await Azion.KV.open('my-namespace');\n\n    await kv.put('user-42', 'active');\n    const value = await kv.get('user-42', 'text');\n\n    return new Response(value ?? 'No value for that key');\n  },\n};"
   }
   ```

2. **Send the create request**

   ```bash
   curl --request POST \
     --url https://api.azion.com/v4/workspace/functions \
     --header 'Accept: application/json' \
     --header 'Authorization: Token [TOKEN VALUE]' \
     --header 'Content-Type: application/json' \
     --data @function.json
   ```

3. **Read the response**

   A `202` carries the function:

   ```json
   {
     "state": "pending",
     "data": {
       "id": 12345,
       "name": "kv-quickstart",
       "last_editor": "user@example.com",
       "last_modified": "2026-01-01T12:00:00.385220Z",
       "product_version": "2.0",
       "active": true,
       "runtime": "azion_js",
       "execution_environment": "application",
       "reference_count": 0
     }
   }
   ```

Record the `id`. The instance references the function by it.

The function does not run yet: the next stage binds it to an application and adds the rule that triggers it. For every method the client carries, refer to [KV client](/en/documentation/devtools/runtime/api-reference/kv-store/).

---

## Instantiate the function and add the rule

An instance binds the function to an application, and a rule decides which requests run the instance. This rule runs it on requests to `/kv-quickstart`.

**Console**

To set both up in Azion Console:

1. **Open the application that runs the function**

   Still in Azion Console, go to **Products Menu** > **Build** > **Applications**, then select your application.

2. **In the Main Settings tab, turn on the Functions module**

3. **Select Save**

4. **Go to the Functions Instances tab**

5. **Select + Function Instance**

6. **Name the instance**

   Enter a name for the instance. For example: `kv-quickstart instance`.

7. **Select the kv-quickstart function**

8. **Select Save**

9. **Go to the Rules Engine tab**

10. **Select + Rule**

11. **Name the rule**

    Enter a name for the rule. For example: `Run kv-quickstart`.

12. **Select Request Phase**

13. **Set the criteria**

    In the **Criteria** section, select the `${uri}` variable and the *is equal* operator, and enter `/kv-quickstart` as the argument.

14. **In the Behaviors section, select Run Function**

15. **Select the instance you created**

16. **Select Save**

The rule runs the instance on every request whose URI is `/kv-quickstart`.

**CLI**

To set both up with the Azion CLI, replace the application id and the function id with your own:

1. **Turn on the Functions module**

   ```bash
   azion update application --application-id <application_id> --functions true
   ```

2. **Create the instance**

   ```bash
   azion create function-instance --application-id <application_id> --function-id <function_id> --name "kv-quickstart instance"
   ```

   The command prints the id of the new instance:

   ```text
   Created Function Instance with ID 12348
   ```

3. **Write the rule to a file**

   Save the following as `rule.json`, with the id of your instance in `attributes.value`:

   ```json
   {
     "name": "Run kv-quickstart",
     "description": "Run the function on /kv-quickstart",
     "active": true,
     "criteria": [
       [
         {
           "conditional": "if",
           "variable": "${uri}",
           "operator": "is_equal",
           "argument": "/kv-quickstart"
         }
       ]
     ],
     "behaviors": [
       {
         "type": "run_function",
         "attributes": { "value": 12348 }
       }
     ]
   }
   ```

4. **Create the rule**

   ```bash
   azion create rules-engine --application-id <application_id> --phase request --file rule.json
   ```

   The command prints the id of the new rule:

   ```text
   Created Rules Engine with ID 234568
   ```

The rule runs the instance on every request whose URI is `/kv-quickstart`.

**API**

Three requests turn on the module, create the instance, and add the rule.

1. **Turn on the Functions module**

   Replace `<application_id>` with [your application ID](/en/documentation/guides/application-development/getting-started/configure-main-settings/):

   ```bash
   curl --request PATCH \
     --url https://api.azion.com/v4/workspace/applications/<application_id> \
     --header 'Accept: application/json' \
     --header 'Authorization: Token [TOKEN VALUE]' \
     --header 'Content-Type: application/json' \
     --data '{
     "modules": {
       "functions": {
         "enabled": true
       }
     }
   }'
   ```

2. **Create the instance**

   Replace `<function_id>` with the `id` the function create returned:

   ```bash
   curl --request POST \
     --url https://api.azion.com/v4/workspace/applications/<application_id>/functions \
     --header 'Accept: application/json' \
     --header 'Authorization: Token [TOKEN VALUE]' \
     --header 'Content-Type: application/json' \
     --data '{
     "name": "kv-quickstart instance",
     "function": <function_id>,
     "args": {},
     "active": true
   }'
   ```

   A `202` carries the instance, and `data.id` is the value the rule selects.

3. **Write the rule to a file**

   The criteria carry `${uri}`, which a shell expands, so the body is sent from a file. Save the following as `rule.json`, with the id of your instance in `attributes.value`:

   ```json
   {
     "name": "Run kv-quickstart",
     "description": "Run the function on /kv-quickstart",
     "active": true,
     "criteria": [
       [
         {
           "conditional": "if",
           "variable": "${uri}",
           "operator": "is_equal",
           "argument": "/kv-quickstart"
         }
       ]
     ],
     "behaviors": [
       {
         "type": "run_function",
         "attributes": { "value": 12347 }
       }
     ]
   }
   ```

4. **Create the rule**

   ```bash
   curl --request POST \
     --url https://api.azion.com/v4/workspace/applications/<application_id>/request_rules \
     --header 'Accept: application/json' \
     --header 'Authorization: Token [TOKEN VALUE]' \
     --header 'Content-Type: application/json' \
     --data @rule.json
   ```

   A `202` carries the rule and the `order` it holds among the rules of the application.

The rule runs the instance on every request whose URI is `/kv-quickstart`.

New rules can take a few minutes to propagate. Wait before you request the URI. For each instance and rule field this guide passes over, refer to [Functions quickstart](/en/documentation/platform/functions/quickstart/).

---

## Request the URI

Your application answers on its own domain. To reach the function, request the URI the rule matches:

```bash
curl https://<your-azion-domain>/kv-quickstart
```

A successful response carries the body the function returns, which is the value it stored under `user-42` and read back: the string `active`. A response carrying `No value for that key` means the read returned `null`, so the key was not found under that name.

Your first namespace holds one key, and a function writes and reads it on every request the rule matches.

---

## Next steps

- [KV client](/en/documentation/devtools/runtime/api-reference/kv-store.md): Every method a function calls against a namespace, with the return types and options each one accepts.
- [Namespaces](/en/documentation/platform/kv-store/namespaces.md): The fields a namespace carries, the three API operations on it, and the error each rejection returns.
- [How KV Store works](/en/documentation/platform/kv-store/how-it-works.md): Where a write lands, and where a read is served from.
- [Best practices](/en/documentation/platform/kv-store/best-practices.md): How to shape a key, and the naming convention behind a name that cannot be changed.
