Skip to content

Embedded Redis Server is a lightweight, in-process Redis-compatible server written in Kotlin. Designed for testing, development, and CI/CD pipelines. Features Spring Boot auto-configuration, RESP2 protocol support, and zero external dependencies. Use it just like H2 Database - simply add the dependency and start coding!

License

Notifications You must be signed in to change notification settings

sudouser777/embedded-redis-server

Repository files navigation

Embedded Redis Server

GitHub Release Build Status License Kotlin Java Spring Boot

A lightweight, embeddable Redis-compatible server written in Kotlin. Perfect for testing, development, and scenarios where you need an in-memory Redis instance without installing Redis itself.

Features

Redis Protocol Compatible - Implements RESP2 protocol

Embedded & Lightweight - Run Redis in-process, no external dependencies

Spring Boot Integration - Auto-configuration support for Spring Boot applications (via a SmartLifecycle adapter; core server is Spring-free)

Easy to Use - Simple API for standalone applications

Fast - Kotlin coroutines for concurrent operations

Testing Friendly - Perfect for unit and integration tests

Graceful Connections - QUIT command supported; client disconnects handled cleanly

Supported Redis Commands

  • Connection: PING, ECHO, HELLO, QUIT, COMMAND COUNT
  • Key-Value: SET, GET, DEL, EXISTS
  • Legacy: SETNX, SETEX (rejects non‑positive TTLs)
  • Hash: HSET, HSETNX, HGET, HMGET, HINCRBY
  • Lists: LPUSH, RPUSH, LPOP, RPOP, LLEN, LMOVE, LRANGE, LTRIM
  • Options: Expiration (EX, PX), Conditional Sets (NX, XX)

Connection handling and binding

  • RESP responses are aligned with Redis semantics:

    • Status replies are used for control responses (e.g., +PONG, +OK)
    • Bulk strings are used for data payloads (GET/ECHO/HGET/HMGET), including null bulk for missing values
  • On invalid RESP framing (malformed protocol), the server closes the connection to avoid stream desynchronization and preserve pipelining guarantees.

  • The server implements RESP2 and explicitly supports the QUIT command. After replying +OK, the server closes the client socket.

  • EOF, connection reset, and broken pipe from clients are treated as normal disconnects and are not logged as errors.

  • The server binds explicitly to the configured host and port:

    • host=127.0.0.1 or ::1 limits access to the local machine only.
    • host=0.0.0.0 (default for standalone) listens on all interfaces.
    • In Spring Boot, the default host is localhost unless overridden via properties.
  • The server implements RESP2 and explicitly supports the QUIT command. After replying +OK, the server closes the client socket.

  • EOF, connection reset, and broken pipe from clients are treated as normal disconnects and are not logged as errors.

  • The server binds explicitly to the configured host and port:

    • host=127.0.0.1 or ::1 limits access to the local machine only.
    • host=0.0.0.0 (default for standalone) listens on all interfaces.
    • In Spring Boot, the default host is localhost unless overridden via properties.

Installation

Gradle

dependencies {
    implementation 'io.github.sudouser777:embedded-redis-server:0.0.3'
}

Maven

<dependency>
    <groupId>io.github.sudouser777</groupId>
    <artifactId>embedded-redis-server</artifactId>
    <version>0.0.3</version>
</dependency>

Usage

1. Standalone Application

import io.github.embeddedredis.RedisServer

fun main() {
    // Create and start the server
    val server = RedisServer(port = 6379, host = "localhost")
    server.start()

    // Server is now running and accepting connections
    println("Redis server started on port 6379")

    // Add shutdown hook
    Runtime.getRuntime().addShutdownHook(Thread {
        server.stop()
    })

    // Keep the application running
    Thread.currentThread().join()
}

2. Spring Boot Integration

Spring support is provided via a SmartLifecycle adapter bean, keeping the core RedisServer free of Spring dependencies. The adapter starts/stops the server with the application lifecycle.

Step 1: Add Dependency

Add the embedded-redis-server dependency to your Spring Boot project.

Step 2: Configure (Optional)

Add configuration to your application.yml or application.properties:

application.yml:

embedded:
  redis:
    enabled: true      # Enable/disable embedded Redis (default: true)
    port: 6379         # Redis port (default: 6379)
    host: localhost    # Bind address (default: localhost)
    auto-start: true   # Auto-start on app startup (default: true)

application.properties:

embedded.redis.enabled=true
embedded.redis.port=6379
embedded.redis.host=localhost
embedded.redis.auto-start=true

Step 3: Use in Your Application

The embedded Redis server will automatically start when your Spring Boot application starts (if embedded.redis.auto-start=true). Under the hood, a RedisServer bean is created and a RedisServerLifecycleAdapter manages its lifecycle.

@SpringBootApplication
class MyApplication

fun main(args: Array<String>) {
    runApplication<MyApplication>(*args)
}

Step 4: Connect with Redis Clients

@Service
class MyService {

    fun useRedis() {
        // Use any Redis client (Jedis, Lettuce, etc.)
        val jedis = Jedis("localhost", 6379)

        jedis.set("key", "value")
        val value = jedis.get("key")

        jedis.close()
    }
}

3. Testing with JUnit

class MyRedisTest {

    companion object {
        private lateinit var server: RedisServer

        @BeforeAll
        @JvmStatic
        fun startServer() {
            server = RedisServer(port = 16379)  // Use different port for tests
            server.start()
        }

        @AfterAll
        @JvmStatic
        fun stopServer() {
            server.stop()
        }
    }

    @Test
    fun testRedisOperations() {
        val jedis = Jedis("localhost", 16379)

        jedis.set("test", "value")
        val result = jedis.get("test")

        assertEquals("value", result)
        jedis.close()
    }
}

4. Spring Boot Test Integration

@SpringBootTest
@TestPropertySource(properties = [
    "embedded.redis.enabled=true",
    "embedded.redis.port=16379"
])
class MySpringBootTest {

    @Autowired
    private lateinit var redisServer: RedisServer

    @Test
    fun testWithEmbeddedRedis() {
        val jedis = Jedis("localhost", 16379)

        jedis.set("spring", "boot")
        val result = jedis.get("spring")

        assertEquals("boot", result)
        jedis.close()
    }
}

Configuration Options

Standalone Configuration

val server = RedisServer(
    port = 6379,           // Port number (default: 6379)
    host = "0.0.0.0"       // Bind address (default: 0.0.0.0)
)

Spring Boot Configuration

Property Type Default Description
embedded.redis.enabled Boolean true Enable/disable embedded Redis
embedded.redis.port Integer 6379 Port for Redis server
embedded.redis.host String localhost Host address to bind
embedded.redis.auto-start Boolean true Auto-start server on app startup

Use Cases

1. Unit Testing

Replace actual Redis with embedded version for fast, isolated tests.

2. Integration Testing

Test Redis-dependent code without external Redis installation.

3. Local Development

Develop applications without installing Redis.

4. CI/CD Pipelines

Run tests in CI without Redis setup complexity.

5. Demos & Prototypes

Quick demos without infrastructure setup.

Performance Considerations

  • In-Memory Only: All data stored in memory (not persisted to disk)
  • Single-Threaded: While coroutines handle concurrency, operations are sequential
  • Development/Testing: Optimized for development/testing, not production workloads
  • Memory: Monitor memory usage for large datasets

Comparison with Alternatives

Feature Embedded Redis Server redis-mock embedded-redis testcontainers-redis
Protocol Compliant ✅ RESP2 ⚠️ Partial ✅ Yes ✅ Yes
Spring Boot Auto-Config ✅ Yes ❌ No ❌ No ❌ No
Pure JVM ✅ Yes ✅ Yes ❌ No (native) ❌ No (Docker)
Lightweight ✅ Yes ✅ Yes ⚠️ Medium ❌ Heavy
No External Dependencies ✅ Yes ✅ Yes ⚠️ Redis binary ❌ Docker required

Limitations

  • Not Production Ready: For development/testing only
  • Limited Commands: Core commands implemented, advanced features not available
  • No Persistence: Data not saved to disk
  • No Clustering: Single instance only
  • No Pub/Sub: Not yet implemented
  • No Transactions: Not yet implemented

Roadmap

  • Additional Redis commands (INCR, DECR, ... )
  • Pub/Sub support
  • Transaction support (MULTI/EXEC)
  • Lua scripting
  • AOF/RDB persistence (optional)
  • RESP3 protocol support

Requirements

  • Java 21 or higher
  • Kotlin 1.9.22 or higher
  • Spring Boot 3.2+ (for Spring integration)

Building from Source

# Clone the repository
git clone https://github.com/sudouser777/embedded-redis-server.git
cd embedded-redis-server

# Build with Gradle
./gradlew build

# Run tests
./gradlew test

# Publish to local Maven repository
./gradlew publishToMavenLocal

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

  1. Fork the repository
  2. Create your feature branch (git checkout -b feature/amazing-feature)
  3. Commit your changes (git commit -m 'Add some amazing feature')
  4. Push to the branch (git push origin feature/amazing-feature)
  5. Open a Pull Request

License

This project is licensed under the Apache License 2.0 - see the LICENSE file for details.

Acknowledgments

  • Inspired by H2 Database embedded mode
  • Built with Kotlin Coroutines for concurrency
  • Uses RESP2 protocol specification

Support

Similar Projects


Made with ❤️ using Kotlin

About

Embedded Redis Server is a lightweight, in-process Redis-compatible server written in Kotlin. Designed for testing, development, and CI/CD pipelines. Features Spring Boot auto-configuration, RESP2 protocol support, and zero external dependencies. Use it just like H2 Database - simply add the dependency and start coding!

Topics

Resources

License

Contributing

Stars

Watchers

Forks

Languages