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 🙏

© 2025 – Pkg Stats / Ryan Hefner

@ideacrafters/fastify-config

v1.0.1

Published

Dynamic configuration management plugin for Fastify

Readme

@ideacrafters/fastify-config

Dynamic configuration management plugin for Fastify applications. Manage runtime configuration without server restarts.

npm version License: MIT

Features

  • Multiple Storage Backends: Memory, File, and Redis support
  • Simple API: Consistent interface across all storage types
  • TypeScript Support: Full type definitions included
  • Zero Dependencies: Only requires fastify-plugin
  • Production Ready: Comprehensive error handling and logging
  • Namespace Support: Organize configs with dot notation
  • Fastify 4 & 5 Compatible: Works with both current and next major versions

Installation

npm install @ideacrafters/fastify-config
# or
yarn add @ideacrafters/fastify-config
# or
pnpm add @ideacrafters/fastify-config

For Redis support:

npm install ioredis

Quick Start

import Fastify from 'fastify';
import fastifyConfig from '@ideacrafters/fastify-config';

const fastify = Fastify();

// Register with default memory store
await fastify.register(fastifyConfig);

// Set configuration values
await fastify.config.set('api.rateLimit', 100);
await fastify.config.set('features.darkMode', true);

// Get configuration values
const rateLimit = await fastify.config.get('api.rateLimit'); // 100
const darkMode = await fastify.config.get('features.darkMode'); // true

// Check existence
const exists = await fastify.config.has('api.rateLimit'); // true

// Delete configuration
await fastify.config.delete('features.darkMode');

Storage Backends

Memory Store (Default)

Best for development and testing. Data is lost on restart.

await fastify.register(fastifyConfig);
// or explicitly
await fastify.register(fastifyConfig, {
  store: 'memory'
});

File Store

Persists configuration to a JSON file. Great for small applications.

await fastify.register(fastifyConfig, {
  store: 'file',
  options: {
    path: './config/dynamic.json',
    pretty: true  // Format JSON with indentation
  }
});

Redis Store

For production applications and distributed systems.

import Redis from 'ioredis';

const redisClient = new Redis({
  host: 'localhost',
  port: 6379
});

await fastify.register(fastifyConfig, {
  store: 'redis',
  options: {
    client: redisClient,
    prefix: 'myapp:config:'  // Key prefix in Redis
  }
});

API Reference

fastify.config.set(key: string, value: any): Promise<boolean>

Set a configuration value. Values are automatically JSON serialized.

await fastify.config.set('timeout', 5000);
await fastify.config.set('user', { name: 'John', role: 'admin' });

fastify.config.get(key: string): Promise<any | null>

Get a configuration value. Returns null if key doesn't exist.

const timeout = await fastify.config.get('timeout');
const user = await fastify.config.get('user');

fastify.config.delete(key: string): Promise<boolean>

Delete a configuration value. Returns true if deleted, false if key didn't exist.

const deleted = await fastify.config.delete('timeout');

fastify.config.has(key: string): Promise<boolean>

Check if a configuration key exists.

const exists = await fastify.config.has('timeout');

Namespace Support

Use dot notation to organize configuration hierarchically:

// Set nested configurations
await fastify.config.set('database.host', 'localhost');
await fastify.config.set('database.port', 5432);
await fastify.config.set('database.credentials.user', 'admin');

// Get nested values
const host = await fastify.config.get('database.host');
const port = await fastify.config.get('database.port');

Note: Namespaces are stored as flat keys with dots, not nested objects.

TypeScript Support

Full TypeScript support with type definitions:

import fastifyConfig, { DynamicConfigOptions } from '@ideacrafters/fastify-config';

const options: DynamicConfigOptions = {
  store: 'file',
  options: {
    path: './config.json',
    pretty: true
  }
};

await fastify.register(fastifyConfig, options);

// TypeScript knows about the config decorator
const value: any = await fastify.config.get('key');

Error Handling

The plugin provides three error types:

  • ConfigStoreError: Base error class for all configuration errors
  • ConnectionError: Store connection issues
  • SerializationError: JSON serialization/deserialization failures
import { SerializationError, ConnectionError } from '@ideacrafters/fastify-config';

try {
  await fastify.config.set('key', circularObject);
} catch (error) {
  if (error instanceof SerializationError) {
    console.error('Failed to serialize value');
  } else if (error instanceof ConnectionError) {
    console.error('Store connection failed');
  }
}

Examples

Feature Flags

// Enable/disable features at runtime
await fastify.config.set('features.newUI', false);

// In your route handler
fastify.get('/dashboard', async (request, reply) => {
  const useNewUI = await fastify.config.get('features.newUI');
  
  if (useNewUI) {
    return reply.view('dashboard-new');
  } else {
    return reply.view('dashboard-legacy');
  }
});

Dynamic Rate Limiting

// Update rate limits without restart
await fastify.config.set('rateLimit.requests', 100);
await fastify.config.set('rateLimit.window', 60000);

// In your rate limit middleware
const requests = await fastify.config.get('rateLimit.requests') || 100;
const window = await fastify.config.get('rateLimit.window') || 60000;

Environment-Specific Configuration

const store = process.env.NODE_ENV === 'production' ? 'redis' : 'file';

await fastify.register(fastifyConfig, {
  store,
  options: store === 'redis' 
    ? { client: redisClient, prefix: 'prod:' }
    : { path: './dev-config.json' }
});

Migration from Static Config

Replace static configuration gradually:

// Before: Static config file
const config = require('./config.json');
const timeout = config.api.timeout;

// After: Dynamic config
const timeout = await fastify.config.get('api.timeout') || 5000;

Performance

  • Memory Store: < 10ms for all operations
  • File Store: < 100ms reads, < 200ms writes
  • Redis Store: < 50ms for simple operations

Testing

import { test } from 'tap';
import Fastify from 'fastify';
import fastifyConfig from '@ideacrafters/fastify-config';

test('config operations', async (t) => {
  const fastify = Fastify();
  await fastify.register(fastifyConfig);
  
  await fastify.config.set('test', 'value');
  const value = await fastify.config.get('test');
  
  t.equal(value, 'value');
  await fastify.close();
});

License

MIT