npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@uploadista/kv-store-memory

v0.1.0

Published

Memory KV store for Uploadista

Readme

@uploadista/kv-store-memory

In-memory key-value store for Uploadista. Perfect for development, testing, and single-process deployments.

Overview

The memory KV store provides a simple, synchronous in-memory storage backend using JavaScript Maps. It's designed for:

  • Development: Instant setup, no external dependencies
  • Testing: Predictable behavior, no network latency
  • Single-Process Servers: Single-machine deployments without state sharing
  • Prototyping: Quick proof-of-concepts

All data is stored in RAM and will be lost when the process exits. For persistent or distributed storage, use Redis, Cloudflare KV, or Filesystem stores.

Installation

npm install @uploadista/kv-store-memory
# or
pnpm add @uploadista/kv-store-memory

Prerequisites

  • Node.js 18+ (JavaScript runtime)
  • No external services required

Quick Start

import { memoryKvStore } from "@uploadista/kv-store-memory";
import { Effect } from "effect";

// Use the memory store layer directly
const program = Effect.gen(function* () {
  // The memoryKvStore layer is already configured
  // No additional setup needed
});

// Run with the memory store
Effect.runSync(program.pipe(Effect.provide(memoryKvStore)));

Features

  • Zero Setup: Works out of the box with no configuration
  • Synchronous Operations: Fast in-memory access (~1μs per operation)
  • Pattern Matching: Prefix-based key listing for batch operations
  • Effect-TS Integration: Full async/error handling with Effect
  • Type Safe: Full TypeScript support with strict typing

API Reference

Main Exports

memoryKvStore: Layer<BaseKvStoreService>

Pre-configured Effect layer providing the BaseKvStoreService with in-memory storage.

import { memoryKvStore } from "@uploadista/kv-store-memory";
import { Effect, Layer } from "effect";

const layer = memoryKvStore;
// Type: Layer<never, never, BaseKvStoreService>

makeMemoryBaseKvStore(): BaseKvStore

Factory function to create a new memory KV store instance. Useful for creating multiple isolated stores.

import { makeMemoryBaseKvStore } from "@uploadista/kv-store-memory";

const store = makeMemoryBaseKvStore();
const value = store.get("key"); // Effect<string | null>

Available Operations

The memory store implements the BaseKvStore interface:

get(key: string): Effect<string | null>

Retrieve a value by key. Returns null if key doesn't exist.

const program = Effect.gen(function* () {
  const value = yield* store.get("user:123");
  // value is either a string or null
});

set(key: string, value: string): Effect<void>

Store a string value. Overwrites existing value if key exists.

const program = Effect.gen(function* () {
  yield* store.set("user:123", JSON.stringify({ name: "Alice" }));
});

delete(key: string): Effect<void>

Remove a key. Safe to call on non-existent keys (no-op).

const program = Effect.gen(function* () {
  yield* store.delete("user:123");
});

list(keyPrefix: string): Effect<string[]>

List all keys matching a prefix. Returns array of key names (without prefix).

const program = Effect.gen(function* () {
  const keys = yield* store.list("user:");
  // Returns: ["123", "456", "789"] for keys ["user:123", "user:456", "user:789"]
});

Configuration

The memory store requires no configuration. Simply import and use:

import { memoryKvStore } from "@uploadista/kv-store-memory";
import { uploadServer } from "@uploadista/server";
import { Effect } from "effect";

const program = Effect.gen(function* () {
  const server = yield* uploadServer;
  // Store is automatically available
});

Effect.runSync(
  program.pipe(
    Effect.provide(memoryKvStore),
    // ... other layers
  )
);

Examples

Example 1: Upload Session Storage

Store and retrieve upload file metadata:

import { makeMemoryBaseKvStore } from "@uploadista/kv-store-memory";
import { Effect } from "effect";

const store = makeMemoryBaseKvStore();

interface UploadMetadata {
  filename: string;
  size: number;
  uploadedAt: string;
}

const program = Effect.gen(function* () {
  // Store metadata
  const metadata: UploadMetadata = {
    filename: "document.pdf",
    size: 2097152,
    uploadedAt: new Date().toISOString(),
  };

  yield* store.set("upload:abc123", JSON.stringify(metadata));

  // Retrieve metadata
  const stored = yield* store.get("upload:abc123");
  const parsed = stored ? JSON.parse(stored) : null;
  console.log(parsed);
  // { filename: "document.pdf", size: 2097152, uploadedAt: "2025-10-21T..." }
});

Effect.runSync(program);

Example 2: Batch Operations

List and process multiple keys:

import { makeMemoryBaseKvStore } from "@uploadista/kv-store-memory";
import { Effect } from "effect";

const store = makeMemoryBaseKvStore();

const program = Effect.gen(function* () {
  // Store multiple items
  yield* store.set("session:user1", JSON.stringify({ token: "abc" }));
  yield* store.set("session:user2", JSON.stringify({ token: "def" }));
  yield* store.set("session:user3", JSON.stringify({ token: "ghi" }));

  // List all sessions
  const sessionKeys = yield* store.list("session:");
  console.log(sessionKeys); // ["user1", "user2", "user3"]

  // Process each session
  for (const key of sessionKeys) {
    const fullKey = `session:${key}`;
    const data = yield* store.get(fullKey);
    console.log(`${fullKey}: ${data}`);
  }
});

Effect.runSync(program);

Example 3: Error Handling

Memory store operations rarely fail, but always handle effects properly:

import { makeMemoryBaseKvStore } from "@uploadista/kv-store-memory";
import { Effect } from "effect";

const store = makeMemoryBaseKvStore();

const program = Effect.gen(function* () {
  const value = yield* store.get("key");

  if (value === null) {
    console.log("Key not found, using default");
    yield* store.set("key", "default-value");
  } else {
    console.log("Value:", value);
  }
});

Effect.runSync(program);

Limitations

  • No Persistence: Data is lost when the process exits
  • Single-Process Only: Not suitable for distributed systems
  • No TTL/Expiration: Values persist until explicitly deleted
  • Memory Growth: No automatic cleanup; responsibility falls to application
  • No Transactions: Individual operations are atomic, but multi-step operations are not

Use Cases

Perfect For:

  • Local development and testing
  • Prototype and MVP applications
  • Single-server deployments (same machine)
  • Unit/integration tests with fast execution

Not Recommended For:

  • Distributed/clustered systems (use Redis instead)
  • Applications requiring data persistence (use Filesystem or Azure)
  • High-memory applications with millions of keys
  • Serverless/edge deployments (use Cloudflare KV)

Performance Characteristics

| Operation | Latency | Scaling | |-----------|---------|---------| | get() | ~1μs | O(1) | | set() | ~1μs | O(1) | | delete() | ~1μs | O(1) | | list() | ~100μs | O(n) where n = matching keys |

Memory usage is proportional to total data stored. 1MB of data ≈ 1MB RAM.

Related Packages

Troubleshooting

Data Lost After Process Restart

This is expected behavior. Memory stores are ephemeral by design. For persistent storage:

// Use filesystem store instead
import { fileKvStore } from "@uploadista/kv-store-filesystem";

const layer = fileKvStore({ directory: "./data" });

Out of Memory Errors

If handling massive files or many concurrent uploads, memory may be exhausted. Solutions:

  1. Reduce In-Flight Uploads: Implement rate limiting at the upload endpoint
  2. Use Streaming: Implement chunked uploads to avoid buffering entire files
  3. Switch to Persistent Store: Use Redis or Filesystem for external state management
// Monitor memory usage
console.log(process.memoryUsage());
// { rss: 45MB, heapTotal: 30MB, heapUsed: 20MB, external: 5MB }

Multiple Instances Share Data?

Each makeMemoryBaseKvStore() call creates an isolated store. To share state:

// These are separate stores - data doesn't cross
const store1 = makeMemoryBaseKvStore();
const store2 = makeMemoryBaseKvStore();

// Use a single instance across your app
const sharedStore = makeMemoryBaseKvStore();
export { sharedStore };

License

See LICENSE in the main repository.

See Also