Skip to content

Getting Started

This guide walks you through installing and using Barrel DocDB. You'll have a working database in under 5 minutes.

Prerequisites

  • Erlang/OTP 27+ (for embedded use or building from source)
  • Docker (optional, for standalone deployment)

Installation

The fastest way to run Barrel DocDB as a standalone server:

docker run -d \
  --name barrel \
  -p 8080:8080 \
  -v barrel_data:/data \
  registry.gitlab.enki.io/barrel-db/barrel_docdb:latest

Verify it's running:

curl http://localhost:8080/health

Add to your rebar.config:

{deps, [
    {barrel_docdb, "0.3.0"}
]}.

Then fetch dependencies:

rebar3 get-deps
rebar3 compile

Clone and build:

git clone https://gitlab.enki.io/barrel-db/barrel_docdb.git
cd barrel_docdb
rebar3 compile
rebar3 shell

Your First Database

Create a Database

curl -X POST http://localhost:8080/db/myapp

Response:

{"name": "myapp", "doc_count": 0}

Store a Document

Create a document with an auto-generated ID:

curl -X POST http://localhost:8080/db/myapp \
  -H "Content-Type: application/json" \
  -d '{
    "type": "user",
    "name": "Alice",
    "email": "alice@example.com",
    "role": "admin"
  }'

Response:

{"id": "d7f3e2a1...", "rev": "1-abc123..."}

Or store with a specific ID:

curl -X PUT http://localhost:8080/db/myapp/user-alice \
  -H "Content-Type: application/json" \
  -d '{
    "type": "user",
    "name": "Alice",
    "email": "alice@example.com"
  }'

Retrieve a Document

curl http://localhost:8080/db/myapp/user-alice

Response:

{
  "id": "user-alice",
  "_rev": "1-abc123...",
  "type": "user",
  "name": "Alice",
  "email": "alice@example.com"
}

Update a Document

Include the _rev field from the previous response:

curl -X PUT http://localhost:8080/db/myapp/user-alice \
  -H "Content-Type: application/json" \
  -d '{
    "_rev": "1-abc123...",
    "type": "user",
    "name": "Alice Smith",
    "email": "alice@example.com",
    "role": "admin"
  }'

Delete a Document

curl -X DELETE "http://localhost:8080/db/myapp/user-alice?rev=2-def456..."

Start the Application

application:ensure_all_started(barrel_docdb).

Create a Database

{ok, _Info} = barrel_docdb:create_db(<<"myapp">>).

Store a Document

With auto-generated ID:

{ok, #{<<"id">> := DocId, <<"rev">> := Rev}} =
    barrel_docdb:put_doc(<<"myapp">>, #{
        <<"type">> => <<"user">>,
        <<"name">> => <<"Alice">>,
        <<"email">> => <<"alice@example.com">>
    }).

With specific ID:

{ok, #{<<"rev">> := Rev}} =
    barrel_docdb:put_doc(<<"myapp">>, #{
        <<"id">> => <<"user-alice">>,
        <<"type">> => <<"user">>,
        <<"name">> => <<"Alice">>
    }).

Retrieve a Document

{ok, Doc} = barrel_docdb:get_doc(<<"myapp">>, <<"user-alice">>).
%% Doc = #{<<"id">> => <<"user-alice">>, <<"_rev">> => <<"1-...">>, ...}

Update a Document

{ok, #{<<"rev">> := NewRev}} =
    barrel_docdb:put_doc(<<"myapp">>, Doc#{
        <<"name">> => <<"Alice Smith">>,
        <<"role">> => <<"admin">>
    }).

Delete a Document

{ok, _} = barrel_docdb:delete_doc(<<"myapp">>, <<"user-alice">>, Rev).

Querying Documents

Barrel DocDB provides declarative queries with automatic path indexing. No need to create indexes manually.

Find all users:

curl -X POST http://localhost:8080/db/myapp/_find \
  -H "Content-Type: application/json" \
  -d '{
    "where": [{"path": ["type"], "value": "user"}]
  }'

Find admins:

curl -X POST http://localhost:8080/db/myapp/_find \
  -H "Content-Type: application/json" \
  -d '{
    "where": [
      {"path": ["type"], "value": "user"},
      {"path": ["role"], "value": "admin"}
    ]
  }'

With pagination:

curl -X POST http://localhost:8080/db/myapp/_find \
  -H "Content-Type: application/json" \
  -d '{
    "where": [{"path": ["type"], "value": "user"}],
    "limit": 10,
    "offset": 0
  }'

Find all users:

{ok, Users, _Meta} = barrel_docdb:find(<<"myapp">>, #{
    where => [{path, [<<"type">>], <<"user">>}]
}).

Find admins:

{ok, Admins, _Meta} = barrel_docdb:find(<<"myapp">>, #{
    where => [
        {path, [<<"type">>], <<"user">>},
        {path, [<<"role">>], <<"admin">>}
    ]
}).

With pagination:

{ok, Results, #{total := Total}} = barrel_docdb:find(<<"myapp">>, #{
    where => [{path, [<<"type">>], <<"user">>}],
    limit => 10,
    offset => 0
}).

Watching for Changes

Subscribe to real-time changes using MQTT-style path patterns.

Stream all changes:

curl http://localhost:8080/db/myapp/_changes/stream

Long-poll for changes:

curl "http://localhost:8080/db/myapp/_changes?feed=longpoll&timeout=30000"

Get changes since a specific point:

curl "http://localhost:8080/db/myapp/_changes?since=5"

Subscribe to all changes:

{ok, SubRef} = barrel_docdb:subscribe(<<"myapp">>, <<"#">>),
receive
    {barrel_change, SubRef, Change} ->
        io:format("Change: ~p~n", [Change])
end.

Subscribe to user changes only:

{ok, SubRef} = barrel_docdb:subscribe(<<"myapp">>, <<"type/user/#">>).

Unsubscribe:

barrel_docdb:unsubscribe(SubRef).

Working with Attachments

Store binary files (images, documents, etc.) alongside your documents.

Store an attachment:

curl -X PUT http://localhost:8080/db/myapp/user-alice/_attachments/photo.jpg \
  -H "Content-Type: image/jpeg" \
  --data-binary @photo.jpg

Retrieve an attachment:

curl http://localhost:8080/db/myapp/user-alice/_attachments/photo.jpg > photo.jpg

Delete an attachment:

curl -X DELETE http://localhost:8080/db/myapp/user-alice/_attachments/photo.jpg

Store an attachment:

Data = <<"Hello, World!">>,
{ok, _} = barrel_docdb:put_attachment(<<"myapp">>, <<"user-alice">>,
    <<"greeting.txt">>, Data).

Retrieve an attachment:

{ok, Binary} = barrel_docdb:get_attachment(<<"myapp">>, <<"user-alice">>,
    <<"greeting.txt">>).

List attachments:

AttNames = barrel_docdb:list_attachments(<<"myapp">>, <<"user-alice">>).
%% Returns [<<"greeting.txt">>]

Configuration

Environment Variables

Variable Default Description
BARREL_DATA_DIR data/barrel_docdb Data directory
BARREL_HTTP_PORT 8080 HTTP server port
BARREL_HTTP_ENABLED true Enable HTTP server

Erlang Configuration

In sys.config:

[
  {barrel_docdb, [
    {data_dir, "data/barrel_docdb"},
    {http_port, 8080},
    {http_enabled, true}
  ]}
].

Next Steps

Now that you have Barrel DocDB running, explore these features:

Troubleshooting

Document Update Fails with Conflict

If you get a conflict error when updating, ensure you're including the current _rev value from the document. Barrel uses MVCC (Multi-Version Concurrency Control) to prevent lost updates.

# Get the current revision first
curl http://localhost:8080/db/myapp/doc1

# Then include _rev in your update
curl -X PUT http://localhost:8080/db/myapp/doc1 \
  -H "Content-Type: application/json" \
  -d '{"_rev": "1-abc...", "name": "updated"}'

Connection Refused

Check that the HTTP server is running:

curl http://localhost:8080/health

If using Docker, verify the container is running:

docker ps | grep barrel

Enable HTTP/2 for Better Performance

For production deployments, enable HTTPS with HTTP/2:

export BARREL_HTTP_TLS_ENABLED=true
export BARREL_HTTP_CERTFILE=/path/to/cert.pem
export BARREL_HTTP_KEYFILE=/path/to/key.pem