{"id":45159,"library":"ioredfour","title":"ioredfour","description":"A Redis binary semaphore (distributed lock) using ioredis. v1.4.1 is the latest stable release. Forked from redfour, it replaces node_redis with ioredis for better performance and supports Redis Cluster (including sharded pub/sub for release notifications). It implements a lock with configurable TTL, minimum replication count, and replication timeout. Active development, low release cadence.","status":"active","version":"1.4.1","language":"javascript","source_language":"en","source_url":"https://github.com/nodemailer/ioredfour","tags":["javascript","redis","semaphore","mutex","node"],"install":[{"cmd":"npm install ioredfour","lang":"bash","label":"npm"},{"cmd":"yarn add ioredfour","lang":"bash","label":"yarn"},{"cmd":"pnpm add ioredfour","lang":"bash","label":"pnpm"}],"dependencies":[{"reason":"Required for Redis and Redis Cluster connections. Must be installed separately (peer dependency).","package":"ioredis","optional":false}],"imports":[{"note":"Package is CommonJS only; ESM import will fail. Use require().","wrong":"import Lock from 'ioredfour';","symbol":"Lock","correct":"const Lock = require('ioredfour');"},{"note":"No default export; module.exports is the Lock class itself.","wrong":"const Lock = require('ioredfour').default;","symbol":"default","correct":"const Lock = require('ioredfour').default || require('ioredfour');"},{"note":"No named export; must import default and handle ambiguous default.","wrong":"import { Lock } from 'ioredfour';","symbol":"Lock","correct":"import pkg from 'ioredfour'; const Lock = pkg.default || pkg;"}],"quickstart":{"code":"const Lock = require('ioredfour');\n\n(async () => {\n    const lock = new Lock({\n        redis: { host: '127.0.0.1', port: 6379 },\n        namespace: 'mylock',\n        minReplications: 1,\n        replicationTimeout: 500\n    });\n\n    const id = Math.random().toString();\n    const acquired = await lock.acquireLock(id, 60000);\n    if (acquired.success) {\n        console.log('Lock acquired');\n        await lock.releaseLock(acquired);\n        console.log('Lock released');\n    } else {\n        console.log('Lock not acquired');\n    }\n\n    lock.quit();\n})().catch(console.error);","lang":"javascript","description":"Demonstrates acquiring and releasing a distributed lock with ioredfour."},"warnings":[{"fix":"Pass an existing ioredis instance: new Lock({ redis: existingClient, namespace: '...' })","message":"The module creates a separate Redis connection by default. To reuse an existing ioredis instance, pass it directly via the 'redis' option.","severity":"gotcha","affected_versions":">=1.0.0"},{"fix":"Ensure Redis server version >=7.0 when using Cluster mode, or avoid using waitAcquireLock.","message":"When using Redis Cluster, sharded pub/sub (SSUBSCRIBE/SPUBLISH) is used for release notifications, requiring Redis 7+. If unavailable, initialization fails.","severity":"gotcha","affected_versions":">=1.0.0"},{"fix":"Set replicationTimeout <= 0.66 * lock TTL in milliseconds.","message":"replicationTimeout must be <= (lock TTL) / 1.5. If set too high, lock logic may break.","severity":"gotcha","affected_versions":">=1.0.0"},{"fix":"For an existing instance, pass the instance directly as the 'redis' option.","message":"The 'redis' option can be a connection string, an object (ioredis options), or an existing ioredis instance. Passing a string will create a new connection.","severity":"gotcha","affected_versions":">=1.0.0"},{"fix":"Always call lock.quit() when you are done using the lock.","message":"After releasing the lock, call lock.quit() to close the underlying Redis connection(s).","severity":"gotcha","affected_versions":">=1.0.0"}],"env_vars":null,"search_vec":"'activ':51 'better':26 'binari':4 'cadenc':55 'cluster':31 'configur':43 'count':47 'develop':52 'distribut':6 'fork':16 'implement':39 'includ':32 'ioredfour':1 'ioredi':9,24 'javascript':56 'latest':13 'lock':7,41 'low':53 'minimum':45 'mutex':59 'node':21,60 'notif':37 'perform':27 'pub/sub':34 'redfour':18 'redi':3,22,30,57 'releas':15,36,54 'replac':20 'replic':46,49 'semaphor':5,58 'shard':33 'stabl':14 'support':29 'timeout':50 'ttl':44 'use':8 'v1.4.1':10","created_at":"2026-06-07T12:53:39.670411+00:00","updated_at":"2026-06-07T12:53:39.670411+00:00","problems":[{"fix":"Use const Lock = require('ioredfour');","cause":"Using ES module import (import) on a CommonJS-only package.","error":"Error: Module \"ioredfour\" does not have a default export"},{"fix":"Call quit() on the Lock instance, e.g., const lock = new Lock(...); ...; lock.quit();","cause":"Trying to call quit() on an object that is not the lock instance (e.g., a lock response object).","error":"TypeError: lock.quit is not a function"},{"fix":"Upgrade Redis to 7.0+ or avoid using waitAcquireLock.","cause":"Redis version <7.0 does not support sharded pub/sub required for Cluster mode.","error":"Redis Cluster: ERR unknown command 'SSUBSCRIBE'"},{"fix":"Ensure lock TTL is sufficient and release is called eventually.","cause":"waitAcquireLock timed out or lock was never released.","error":"LockError: Lock not acquired after wait"}],"ecosystem":"npm","meta_description":null,"install_score":null,"quickstart_score":null,"quickstart_tag":null,"pypi_latest":null,"cli_name":null,"cli_version":null,"type":"library","homepage":"https://github.com/nodemailer/ioredfour#readme","github":"https://github.com/nodemailer/ioredfour","docs":null,"changelog":null,"pypi":null,"npm":"ioredfour","openapi_spec":null,"status_page":null,"smithery":null,"categories":["storage"],"base_url":null,"auth_type":null,"provenance":{"verified_status":null,"verified_at":null,"last_verified":"2026-06-07","next_check":"2026-09-05","install_tag":null}}