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

@owlmeans/redis

v0.1.1

Published

Redis service integration for OwlMeans Common server applications. This package provides a server-side Redis service implementation with clustering support, connection management, and multi-layer support designed for caching, session storage, and high-per

Readme

@owlmeans/redis

Redis service integration for OwlMeans Common server applications. This package provides a server-side Redis service implementation with clustering support, connection management, and multi-layer support designed for caching, session storage, and high-performance data operations.

Overview

The @owlmeans/redis package extends the OwlMeans resource system to provide Redis-specific functionality including:

  • Redis Service Integration: Factory functions for creating Redis services with connection management
  • Cluster Support: Automatic Redis cluster and sentinel configuration
  • Connection Pooling: Efficient Redis connection management with proper cleanup
  • Multi-Layer Support: Integration with OwlMeans context layer system for proper data isolation
  • Prefix Management: Automatic key prefixing for namespace isolation

This package follows the OwlMeans "quadra" pattern as a server-side implementation complementing the basic @owlmeans/redis-resource package.

Installation

npm install @owlmeans/redis

Dependencies

This package requires Redis client library and integrates with:

  • @owlmeans/redis-resource: Base Redis resource definitions
  • @owlmeans/server-context: Server context management
  • @owlmeans/resource: Base resource service patterns
  • ioredis: High-performance Redis client library

Core Concepts

Redis Service

The Redis service provides connection management and extends the base database service with Redis-specific functionality like clustering and prefix management.

Connection Management

Manages Redis connections with support for clustering, sentinels, and proper connection lifecycle management including graceful shutdown.

Layer Integration

Supports multi-layer data isolation through the OwlMeans context layer system, allowing service-specific and entity-specific Redis configurations.

API Reference

Types

RedisMeta

Metadata interface for Redis-specific configuration extending ioredis options.

interface RedisMeta extends RedisOptions {
  masterNumber?: number  // Master node count for cluster
  slaveNumber?: number   // Slave node count for cluster
}

Factory Functions

makeRedisService(alias?: string): RedisDbService

Creates a Redis service instance with connection management and clustering capabilities.

Parameters:

  • alias (optional): Service alias (default: DEFAULT_ALIAS)

Returns: RedisDbService instance

Methods:

  • db(configAlias?: string): Promise<RedisDb>: Gets Redis database instance with prefix for the configuration
  • initialize(configAlias?: string): Promise<void>: Initializes Redis connection with cluster setup
  • reinitializeContext<T>(context: BasicContext<ServerConfig>): T: Reinitializes service with new context

Example:

import { makeRedisService } from '@owlmeans/redis'

const redisService = makeRedisService('cache')

// Initialize with configuration
await redisService.initialize('prod-config')

// Get database instance with prefix
const db = await redisService.db('prod-config')

// Use Redis operations
await db.client.set('user:123', JSON.stringify(userData))
const user = await db.client.get('user:123')

appendRedis<C, T>(context: T, alias?: string): T

Convenience function to create and register a Redis service with a context.

Parameters:

  • context: Server context instance
  • alias (optional): Service alias (default: DEFAULT_ALIAS)

Returns: The context with Redis service registered

Example:

import { appendRedis } from '@owlmeans/redis'
import { makeServerContext } from '@owlmeans/server-context'

const context = makeServerContext(serverConfig)
const contextWithRedis = appendRedis(context, 'session-store')

await contextWithRedis.configure().init()

// Access Redis service
const redisService = context.service('session-store')

Redis Database Operations

The Redis service provides a database interface with automatic prefixing:

RedisDb

Database instance with client and prefix management.

interface RedisDb {
  client: RedisClient  // ioredis client instance (duplicated for isolation)
  prefix: string       // Key prefix for namespace isolation
}

Usage:

const db = await redisService.db('config-alias')

// Keys are automatically prefixed
await db.client.set('session:user123', sessionData)
await db.client.get('session:user123')

// Use Redis operations with prefix isolation
await db.client.hmset('user:profile', profileData)
const profile = await db.client.hgetall('user:profile')

Cluster Support

The service automatically handles Redis cluster and sentinel configuration:

// Configuration with cluster hosts
const config = {
  alias: 'cluster-config',
  host: ['redis1.example.com', 'redis2.example.com', 'redis3.example.com'],
  port: 6379,
  database: 'app-cache',
  // Additional cluster options in meta
  meta: {
    masterNumber: 3,
    slaveNumber: 6,
    enableReadyCheck: true,
    maxRetriesPerRequest: 3
  }
}

// Service automatically detects cluster and sets up connections
await redisService.initialize('cluster-config')

Constants

DEFAULT_ALIAS

Default service alias for Redis services.

const DEFAULT_ALIAS = DEFAULT_DB_ALIAS  // From @owlmeans/redis-resource

Usage Examples

Basic Redis Service Setup

import { makeRedisService } from '@owlmeans/redis'
import { makeServerContext } from '@owlmeans/server-context'

// Create server context with Redis configuration
const context = makeServerContext({
  service: 'my-app',
  type: AppType.Backend,
  layer: Layer.Service,
  dbs: [{
    alias: 'main-cache',
    service: 'redis',
    host: 'localhost',
    port: 6379,
    database: 'app-cache'
  }]
})

// Create and register Redis service
const redisService = makeRedisService('redis')
context.registerService(redisService)

// Initialize context
await context.configure().init()

// Use Redis
const db = await redisService.db('main-cache')
await db.client.set('key', 'value')

Using appendRedis Helper

import { appendRedis } from '@owlmeans/redis'

const context = makeServerContext(config)
const contextWithRedis = appendRedis(context)

await contextWithRedis.configure().init()

const redisService = context.service('redis')
const db = await redisService.db()

Session Storage

// Configure Redis for session storage
const sessionConfig = {
  alias: 'session-store',
  service: 'redis',
  host: 'localhost',
  port: 6379,
  database: 'sessions'
}

const redisService = makeRedisService('redis')
await redisService.initialize('session-store')

const db = await redisService.db('session-store')

// Store session data
const sessionId = 'sess_123456'
const sessionData = {
  userId: 'user_789',
  loginTime: Date.now(),
  permissions: ['read', 'write']
}

await db.client.setex(`session:${sessionId}`, 3600, JSON.stringify(sessionData))

// Retrieve session data
const rawSession = await db.client.get(`session:${sessionId}`)
const session = JSON.parse(rawSession)

Caching with TTL

const cacheService = makeRedisService('cache')
await cacheService.initialize('cache-config')

const db = await cacheService.db('cache-config')

// Cache with expiration
await db.client.setex('user:profile:123', 300, JSON.stringify(userProfile)) // 5 minutes

// Cache with complex data structures
await db.client.hmset('stats:daily', {
  visitors: 1234,
  pageViews: 5678,
  lastUpdated: Date.now()
})
await db.client.expire('stats:daily', 86400) // 24 hours

// Get cached data
const cachedProfile = await db.client.get('user:profile:123')
const stats = await db.client.hgetall('stats:daily')

Multi-Configuration Setup

const context = makeServerContext({
  service: 'multi-redis-app',
  type: AppType.Backend,
  layer: Layer.Service,
  dbs: [
    {
      alias: 'session-store',
      service: 'redis',
      host: 'sessions.redis.example.com',
      database: 'sessions',
      meta: { db: 0 }
    },
    {
      alias: 'cache-store',
      service: 'redis',
      host: 'cache.redis.example.com',
      database: 'cache',
      meta: { db: 1 }
    }
  ]
})

const redisService = makeRedisService('redis')
context.registerService(redisService)

await context.configure().init()

// Use different Redis instances
const sessionDb = await redisService.db('session-store')
const cacheDb = await redisService.db('cache-store')

// Operations are isolated by configuration
await sessionDb.client.set('user:session', sessionData)
await cacheDb.client.set('user:profile', profileData)

Cluster Configuration

const clusterConfig = {
  service: 'cluster-app',
  type: AppType.Backend,
  layer: Layer.Service,
  dbs: [{
    alias: 'cluster-cache',
    service: 'redis',
    host: [
      'redis1.cluster.example.com',
      'redis2.cluster.example.com', 
      'redis3.cluster.example.com'
    ],
    port: 6379,
    database: 'clustered-cache',
    meta: {
      enableReadyCheck: true,
      maxRetriesPerRequest: 3,
      retryDelayOnFailover: 100,
      masterNumber: 3,
      slaveNumber: 6
    }
  }]
}

const context = makeServerContext(clusterConfig)
const redisService = makeRedisService('redis')
context.registerService(redisService)

// Service automatically handles cluster setup
await context.configure().init()

const db = await redisService.db('cluster-cache')
// Operations work transparently across cluster

Service Reinitialization

// Original context
const originalContext = makeServerContext(config)
const redisService = makeRedisService()
originalContext.registerService(redisService)

// Later, reinitialize with new context
const newContext = makeServerContext(newConfig)
const reinitializedService = redisService.reinitializeContext(newContext)

// Service now uses new context configuration
await reinitializedService.initialize()

Pub/Sub Operations

const redisService = makeRedisService('pubsub')
await redisService.initialize('pubsub-config')

const db = await redisService.db('pubsub-config')

// Subscribe to channels
await db.client.subscribe('notifications')
db.client.on('message', (channel, message) => {
  console.log(`Received from ${channel}: ${message}`)
})

// Publish messages
await db.client.publish('notifications', JSON.stringify({
  type: 'user-login',
  userId: '123',
  timestamp: Date.now()
}))

Configuration

Redis service configuration is handled through the server context's database configuration:

interface DatabaseConfig {
  alias: string                    // Configuration alias
  service: string                  // Service name ('redis')
  host: string | string[]          // Redis host(s)
  port?: number                    // Redis port
  database: string                 // Database prefix/namespace
  username?: string                // Authentication username
  password?: string                // Authentication password
  serviceSensitive?: boolean       // Enable service-layer isolation
  entitySensitive?: boolean        // Enable entity-layer isolation
  meta?: RedisMeta                 // Redis-specific options
}

Redis-Specific Meta Options

interface RedisMeta extends RedisOptions {
  masterNumber?: number            // Master node count for cluster
  slaveNumber?: number             // Slave node count for cluster
  // Plus all ioredis options:
  db?: number                      // Redis database number
  connectTimeout?: number          // Connection timeout
  commandTimeout?: number          // Command timeout
  retryDelayOnFailover?: number    // Failover retry delay
  enableReadyCheck?: boolean       // Enable ready check
  maxRetriesPerRequest?: number    // Max retries per request
  // ... and many more ioredis options
}

Error Handling

The package provides descriptive error messages for common issues:

  • Client replacement: Thrown when attempting to replace existing Redis client
  • Context assertion: Thrown when service context is invalid
  • Connection errors: Propagated from ioredis client
try {
  await redisService.initialize('config-alias')
} catch (error) {
  if (error.message.includes('Cannot replace existing redis client')) {
    // Handle client replacement error
  }
}

Performance Considerations

  • Connection Pooling: ioredis handles connection pooling automatically
  • Client Duplication: Each db() call creates a duplicate client for isolation
  • Cluster Latency: Cluster setup may add initialization time
  • Memory Usage: Multiple Redis connections increase memory usage
  • Key Prefixing: Adds minimal overhead for namespace isolation

Security Considerations

Connection Security

  • Use authentication credentials for production Redis instances
  • Configure TLS/SSL for Redis connections when needed
  • Restrict Redis access to necessary IP addresses

Data Security

  • Be cautious with sensitive data in Redis (consider encryption)
  • Use appropriate TTL values to limit data exposure time
  • Implement proper access controls at the application level

Namespace Isolation

  • Use layer-sensitive configurations for multi-tenant applications
  • Leverage prefix management for data isolation between services

Integration with OwlMeans Ecosystem

This package integrates with:

  • @owlmeans/redis-resource: Base Redis resource types and interfaces
  • @owlmeans/server-context: Server context and configuration management
  • @owlmeans/resource: Base resource service patterns
  • @owlmeans/mongo: For multi-database architectures

Best Practices

  1. Use appropriate TTL values for cached data to prevent memory bloat
  2. Configure clustering for production high-availability
  3. Separate Redis configurations by use case (cache vs sessions vs pub/sub)
  4. Monitor Redis memory usage and implement eviction policies
  5. Use connection pooling efficiently with proper client management

Related Packages

  • @owlmeans/redis-resource: Base Redis resource definitions
  • @owlmeans/mongo: MongoDB service implementation
  • @owlmeans/server-context: Server context management
  • @owlmeans/resource: Base resource service patterns

Redis Use Cases

Caching

  • API response caching
  • Database query result caching
  • Computed value caching

Session Storage

  • User session management
  • Authentication token storage
  • Shopping cart persistence

Real-time Features

  • Pub/Sub messaging
  • Live notifications
  • Real-time analytics

Rate Limiting

  • API rate limiting
  • Request throttling
  • Usage tracking