This project implements a lightweight in-memory key-value storage service exposed through an HTTP API. The system allows clients to perform basic operations such as storing, retrieving, and deleting values associated with keys.
The service is implemented in Erlang, follows a simple RESTful design and communicates using JSON over HTTP.
The system is designed under the following assumptions: it runs as a single-node service and prioritizes fast concurrent read and write operations using an in-memory storage model. All data is stored at runtime and is not persisted to disk.
The application follows a three‑layer design:
| Layer | Module | Responsibility |
|---|---|---|
| HTTP Layer | http_handler.erl |
Acts as the system entry point, exposing a RESTful HTTP API. It translates external HTTP requests into internal operations and ensures consistent communication through JSON and standard HTTP status codes. |
| Storage Interface | storage_interface.erl |
Defines a bridge between the HTTP layer and the storage implementation. It provides a stable contract for data operations, ensuring that higher-level logic remains decoupled from storage-specific details. |
| Storage Backend | storage_ets.erl |
Provides the concrete implementation of the storage contract using Erlang Term Storage (ETS). It manages the in-memory data table and performs all data operations while supporting concurrent access. |
- Client sends HTTP request (GET, PUT, DELETE)
http_handlerprocesses request and extracts parametersstorage_interfaceforwards operation to backendstorage_etsexecutes ETS operation- Result is returned back through the layers
- HTTP response is generated
The system is implemented using the following technologies:
- HTTP Layer: Cowboy is used as the HTTP server to handle incoming requests and route them to the application logic. JSON encoding and decoding is performed using JSX.
- Storage Backend: ETS is used as the in-memory storage engine, providing fast concurrent access to key-value data.
The service exposes a RESTful HTTP API for managing key-value pairs. All requests and responses are encoded in JSON, and the service uses standard HTTP status codes to indicate success or failure.
Retrieves the current value associated with a given key.
HTTP Method: GET
Endpoint: /keys/:key
Request Body: None
| Status Code | Meaning | Response Body |
|---|---|---|
| 200 OK | Key exists and value was retrieved successfully | { "key": "<key>", "value": <stored_value> } |
| 404 Not Found | Key does not exist in the table | { "error": "key not found" } |
Stores or updates the value associated with a given key.
HTTP Method: PUT
Endpoint: /keys/:key
Request Body: { "value": <any JSON value> }
| Status Code | Meaning | Response Body |
|---|---|---|
| 200 OK | Value successfully stored or updated | { "key": "<key>", "value": <stored_value> } |
| 400 Bad Request | Invalid request body (empty body, invalid JSON, or missing value field) |
{ "error": "<reason>" } |
Deletes the value associated with a given key.
HTTP Method: DELETE
Endpoint: /keys/:key
Request Body: None
| Status Code | Meaning | Response Body |
|---|---|---|
| 200 OK | Key successfully deleted | { "key": "<key>" } |
| 404 Not Found | Key does not exist in the table | { "error": "key not found" } |
src/ ├── http_handler.erl # HTTP layer ├── storage_interface.erl # Storage abstraction layer (API between HTTP and backend) ├── storage_ets.erl # ETS in-memory key-value storage implementation │ ├── http_service_app.erl # OTP application entry point ├── http_service_sup.erl # Supervisor (placeholder for future supervised processes; currently has no children) └── http_service.app.src # Application resource file (metadata, dependencies) │ scripts/ │ └── test.sh # Integration test script for API validation
- Erlang/OTP installed
- rebar3 build tool installed
From the project root directory, compile the project using:
rebar3 compileStart an Erlang shell:
rebar3 shell./test.sh