---
title: 'KV Store'
description: 'Durable key-value state across workflow runs: get, set, atomic append.'
updated: 2026-07-09
---

# KV Store

**Node type:** `state:kv`  
**Category:** `Data`

## Description

Small durable state that survives between runs: dedupe lists, publish logs, counters. Entries are always scoped to your account; the namespace defaults to the current workflow, so two of your workflows only share state when both set the same `namespace` explicitly.

Operations:

- `get` returns `{ found, value }`. A missing key gives `found: false` and `value: null`, never an error.
- `set` upserts the wired value and returns what was stored.
- `append` treats the stored value as an array and appends the wired value atomically (a single database statement, so two concurrent runs never lose an element). Non-array existing values are wrapped into an array first.

Each entry caps at 1 MB; an append that would exceed the cap fails loudly and writes nothing.

## Canvas ports

These appear as port handles on the left side of the node.

| ID      | Label     | Details                                             |
| ------- | --------- | --------------------------------------------------- |
| `value` | **Value** | `JSON` · required for `set` / `append`              |
| `key`   | **Key**   | `TEXT` · optional; overrides the `key` config field |

## Sidebar config

These render as form fields in the right-side config panel when the node is selected.

| ID          | Label         | Details                                                                                                    |
| ----------- | ------------- | ---------------------------------------------------------------------------------------------------------- |
| `operation` | **Operation** | `TEXT` _(required)_ · options: `get`, `set`, `append`                                                      |
| `key`       | **Key**       | `TEXT` _(required unless wired)_                                                                           |
| `namespace` | **Namespace** | `TEXT` · optional. Defaults to this workflow's id; set explicitly to share state between sibling workflows |

## Outputs

| ID      | Label     | Type      |
| ------- | --------- | --------- |
| `value` | **Value** | `JSON`    |
| `found` | **Found** | `BOOLEAN` |

`append` also reports a `count` (length of the stored array) in the result.

## Worked example: append-dedupe pattern

Publish each topic at most once, across daily runs:

1. `state:kv` (`get`, key `published-topics`) reads the list published so far.
2. `exec:code` filters the day's candidates against it:

   ```js
   const seen = new Set(inputs.published || []);
   const fresh = inputs.candidates.filter((t) => !seen.has(t.id));
   if (fresh.length === 0) {
     return { __fail: true, error: 'nothing new to publish' };
   }
   return fresh[0];
   ```

3. After the publish step succeeds, a second `state:kv` (`append`, same key) appends the published topic id. The append is atomic, so overlapping runs cannot drop an id from the list.

---

_Auto-generated from the Wireflow node registry._

---

Documentation index: fetch https://www.wireflow.ai/llms.txt for the full list of Wireflow docs.
