Skip to content

KV Storage

Every TMA.sh project includes a key-value store. No database setup, no connection strings — import the SDK and start reading and writing data.

import { createTMA } from '@tma.sh/sdk';
const tma = createTMA({ projectId: 'your-project-id' });

Store any JSON-serializable value:

await tma.kv.set('user:123:preferences', {
theme: 'dark',
language: 'en',
notifications: true,
});

Setting a key that already exists overwrites the previous value.

Retrieve a value by key. Returns null if the key does not exist:

const prefs = await tma.kv.get('user:123:preferences');
// { theme: 'dark', language: 'en', notifications: true }

Remove a key and its value:

await tma.kv.remove('user:123:preferences');

Removing a key that does not exist is a no-op.

Retrieve all keys matching a prefix:

const result = await tma.kv.list('user:123:');
const keyNames = result.keys.map(k => k.name);
// ['user:123:preferences', 'user:123:scores', 'user:123:inventory']

The list() method returns an object with keys (an array of { name: string } objects) and list_complete (a boolean indicating whether all matching keys have been returned). Use colons as separators to create a natural key hierarchy. Fetch individual values with kv.get().

PropertyLimit
Max value size128 KB
Max key size512 bytes
ConsistencyEventually consistent (~60s)

Values are stored as JSON. The 128 KB limit applies to the serialized JSON string. Keys must be valid UTF-8 strings.

Eventually consistent means that after a write, subsequent reads from different edge locations may return the previous value for up to 60 seconds. Reads from the same location that performed the write are immediately consistent.

Use colon-separated segments for structured keys:

{entity}:{id}:{field}

Examples:

user:123:preferences
user:123:scores
leaderboard:global
session:abc123
feature:dark-mode
cache:api:weather:london

This convention makes prefix-based listing predictable and keeps your keyspace organized.

KV storage works well for:

  • User preferences — theme, language, notification settings
  • Feature flags — toggle features per user or globally
  • Leaderboards — store scores keyed by user ID, list by prefix
  • Session data — temporary state between page loads
  • Cached API responses — store third-party API results with a TTL key pattern

KV storage is not a database. For the following use cases, use the managed D1 database (Pro and Team plans) or connect an external database like Supabase or Turso:

  • Relational data — queries that join tables or filter on multiple columns
  • Transactions — operations that must succeed or fail atomically
  • Complex queries — full-text search, aggregations, sorting by multiple fields
  • Strong consistency — reads that must always return the latest write

See Database for the D1 binding API reference, or the Authentication page for how to connect TMA.sh JWTs to Supabase.

In API routes, use the createKV() helper from @tma.sh/sdk/server for a typed wrapper around the KV binding. See Server Helpers for details.