{"id":50960792,"url":"https://github.com/amscotti/facet","last_synced_at":"2026-06-18T14:01:28.473Z","repository":{"id":344628263,"uuid":"1131993554","full_name":"amscotti/facet","owner":"amscotti","description":"Facet is a high-performance, Redis-compatible in-memory database server written in Crystal","archived":false,"fork":false,"pushed_at":"2026-03-15T15:55:05.000Z","size":97,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-03-16T04:42:41.368Z","etag":null,"topics":["crystal-lang","database","in-memory","redis"],"latest_commit_sha":null,"homepage":"","language":"Crystal","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/amscotti.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-01-11T05:11:01.000Z","updated_at":"2026-03-15T15:55:06.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/amscotti/facet","commit_stats":null,"previous_names":["amscotti/facet"],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/amscotti/facet","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/amscotti%2Ffacet","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/amscotti%2Ffacet/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/amscotti%2Ffacet/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/amscotti%2Ffacet/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/amscotti","download_url":"https://codeload.github.com/amscotti/facet/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/amscotti%2Ffacet/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34493363,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-18T02:00:06.871Z","response_time":128,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["crystal-lang","database","in-memory","redis"],"created_at":"2026-06-18T14:01:27.636Z","updated_at":"2026-06-18T14:01:28.459Z","avatar_url":"https://github.com/amscotti.png","language":"Crystal","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Facet\n\nFacet is a high-performance, Redis-compatible in-memory database server written in Crystal. Designed as a drop-in replacement for Redis, Facet implements the RESP2/RESP3 protocol and provides unique features tailored for testing and development workflows.\n\n## Key Features\n\n- **Drop-in Redis Replacement**: Compatible with existing Redis clients and tools including `redis-cli`\n- **Database Copy and Clone**: Create isolated copies of databases for test isolation without data corruption\n- **Dynamic Database Management**: Create, freeze, and manage named databases at runtime\n- **High Performance**: Fiber-based concurrency with configurable worker pools\n- **Binary Safe**: All keys and values handled as raw bytes\n- **TTL Support**: Full key expiration with millisecond precision\n\n## Use Cases\n\n### Test Isolation\n\nFacet's database copy feature makes it ideal for integration testing:\n\n```\n# Set up baseline test data once\nredis-cli DBCREATE baseline\nredis-cli DBSELECT baseline\nredis-cli SET user:1 \"test_user\"\nredis-cli DBFREEZE baseline\n\n# Before each test, create an isolated copy\nredis-cli DBCOPY baseline test_run_1\nredis-cli DBSELECT test_run_1\n# Run tests against isolated data...\n\n# Clean up after test\nredis-cli DBDROP test_run_1\n```\n\nEach test runs against its own database copy, preventing test pollution and enabling parallel test execution.\n\n### Local Development\n\nUse Facet as a lightweight Redis alternative during development without the overhead of running a full Redis installation.\n\n## Installation\n\n### Docker (Recommended)\n\n```bash\ndocker pull ghcr.io/amscotti/facet:latest\ndocker run -p 6379:6379 ghcr.io/amscotti/facet:latest\n```\n\n### Download Binary\n\nDownload pre-built binaries from the [Releases](https://github.com/amscotti/facet/releases) page:\n\n- `facet-linux-amd64.tar.gz` - Linux (static binary)\n- `facet-macos-amd64.tar.gz` - macOS Intel\n- `facet-macos-arm64.tar.gz` - macOS Apple Silicon\n\n### Building from Source\n\nPrerequisites:\n- Crystal 1.10 or later\n- Shards (Crystal's dependency manager)\n\n```bash\ngit clone https://github.com/amscotti/facet.git\ncd facet\nshards install\ncrystal build src/facet.cr -o facet --release\n```\n\n## Usage\n\n### Starting the Server\n\n```bash\n# Binary\n./facet\n\n# Docker\ndocker run -p 6379:6379 ghcr.io/amscotti/facet:latest\n\n# Docker with custom workers\ndocker run -p 6379:6379 -e FACET_WORKERS=8 ghcr.io/amscotti/facet:latest\n```\n\n```bash\n# Verify it's running\nredis-cli ping\n# PONG\n```\n\n### Configuration\n\n| Variable | Default | Description |\n|----------|---------|-------------|\n| `FACET_WORKERS` | 4 | Number of worker fibers for handling connections |\n\n### Connecting with Redis Clients\n\nFacet works with any Redis client library:\n\n```python\n# Python\nimport redis\nr = redis.Redis(host='localhost', port=6379)\nr.set('key', 'value')\n```\n\n```javascript\n// Node.js\nimport { createClient } from 'redis';\nconst client = createClient();\nawait client.connect();\nawait client.set('key', 'value');\n```\n\n```ruby\n# Ruby\nrequire 'redis'\nredis = Redis.new\nredis.set('key', 'value')\n```\n\n## Supported Commands\n\n### String Commands\n`GET`, `SET`, `SETEX`, `SETNX`, `PSETEX`, `GETSET`, `GETDEL`, `GETEX`, `GETRANGE`, `SETRANGE`, `STRLEN`, `APPEND`, `MGET`, `MSET`, `MSETNX`, `INCR`, `INCRBY`, `INCRBYFLOAT`, `DECR`, `DECRBY`\n\n### Key Commands\n`DEL`, `EXISTS`, `KEYS`, `TYPE`, `RENAME`, `RENAMENX`, `SCAN`, `EXPIRE`, `EXPIREAT`, `PEXPIRE`, `PEXPIREAT`, `TTL`, `PTTL`, `PERSIST`\n\n### List Commands\n`LPUSH`, `LPUSHX`, `RPUSH`, `RPUSHX`, `LPOP`, `RPOP`, `LLEN`, `LRANGE`, `LINDEX`, `LSET`, `LINSERT`, `LREM`, `LTRIM`, `LMOVE`, `LPOS`\n\n### Hash Commands\n`HSET`, `HSETNX`, `HGET`, `HMSET`, `HMGET`, `HGETALL`, `HDEL`, `HEXISTS`, `HLEN`, `HKEYS`, `HVALS`, `HINCRBY`, `HINCRBYFLOAT`, `HSTRLEN`, `HSCAN`\n\n### Set Commands\n`SADD`, `SREM`, `SMEMBERS`, `SISMEMBER`, `SMISMEMBER`, `SCARD`, `SPOP`, `SRANDMEMBER`, `SMOVE`, `SDIFF`, `SDIFFSTORE`, `SINTER`, `SINTERSTORE`, `SUNION`, `SUNIONSTORE`, `SSCAN`\n\n### Sorted Set Commands\n`ZADD`, `ZREM`, `ZSCORE`, `ZMSCORE`, `ZRANK`, `ZREVRANK`, `ZCARD`, `ZCOUNT`, `ZRANGE`, `ZREVRANGE`, `ZRANGEBYSCORE`, `ZRANGESTORE`, `ZINCRBY`, `ZPOPMIN`, `ZPOPMAX`, `ZRANDMEMBER`, `ZSCAN`\n\n### Transaction Commands\n`MULTI`, `EXEC`, `DISCARD`, `WATCH`, `UNWATCH`\n\n### Server Commands\n`PING`, `ECHO`, `QUIT`, `SELECT`, `DBSIZE`, `FLUSHDB`, `FLUSHALL`, `COMMAND`, `CONFIG`\n\n### Facet Extensions\n\nThese commands extend Redis functionality for database management:\n\n| Command | Description |\n|---------|-------------|\n| `DBCREATE \u003cname\u003e` | Create a new named database |\n| `DBDROP \u003cname\u003e` | Delete a named database |\n| `DBSELECT \u003cname\u003e` | Switch to a named database |\n| `DBLIST` | List all databases |\n| `DBCOPY \u003csource\u003e \u003cdest\u003e` | Copy database to new name |\n| `DBCOPYKEYS \u003csource\u003e \u003cdest\u003e \u003cpattern\u003e` | Copy matching keys between databases |\n| `DBFREEZE \u003cname\u003e` | Make database read-only |\n| `DBUNFREEZE \u003cname\u003e` | Make database writable |\n| `DBINFO [name]` | Get database information |\n| `DBRESET \u003cname\u003e` | Clear all data in database |\n\n## Development\n\n### Running Tests\n\n```bash\n# Run all tests\ncrystal spec\n\n# Run specific test file\ncrystal spec spec/commands/string_commands_spec.cr\n\n# Run tests matching a pattern\ncrystal spec --example \"SET command\"\n```\n\n### Linting\n\n```bash\nbin/ameba\n```\n\n### Type Checking\n\n```bash\ncrystal build src/facet.cr --no-codegen\n```\n\n## Architecture\n\nFacet uses a fiber-based concurrency model:\n\n1. **TCP Server**: Accepts connections and distributes to worker pool\n2. **Worker Fibers**: Process client connections concurrently\n3. **RESP Parser**: Streaming protocol parser for Redis wire format\n4. **Command Handler**: Dispatches commands to appropriate handlers\n5. **Storage Layer**: Hash-based storage with lazy TTL expiration\n\n## Contributing\n\n1. Fork the repository\n2. Create your feature branch (`git checkout -b feature/my-feature`)\n3. Commit your changes (`git commit -am 'Add my feature'`)\n4. Push to the branch (`git push origin feature/my-feature`)\n5. Create a Pull Request\n\nPlease ensure all tests pass and code follows the existing style.\n\n## License\n\nApache License 2.0 - See [LICENSE](LICENSE) for details.\n\n## Author\n\nAnthony Scotti\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Famscotti%2Ffacet","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Famscotti%2Ffacet","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Famscotti%2Ffacet/lists"}