General discussion, cross-repository efforts and common information for projects in the community.
📌 Which module should I use? What is
abstract-level
? Head over to the FAQ.
Click to expand
Level is a community and a collection of Node.js modules for creating transparent databases. A solid set of primitives enable powerful databases to be built in userland. They can be embedded or networked, persistent or transient - in short, tailored to your needs.
At the core of Level are simple key-value stores that follow the characteristics of LevelDB. LevelDB is a key-value store built by Google, used in Google Chrome and many other products. It supports arbitrary byte arrays as both keys and values, singular reads and writes, batched writes and bi-directional iterators. LevelDB sorts entries lexicographically by keys which, when combined with ranged iterators, makes for a very powerful query mechanism.
To bring those concepts to Node.js and other JavaScript runtimes, Level utilizes idiomatic Node.js interfaces like streams, events and buffers. It offers a rich set of data types through encodings and allows for extensions like subleveldown
to split a database into evented sections. Underlying stores can be easily swapped to target a wide range of runtime environments. The most common store is leveldown
which is a pure C++ binding to LevelDB. Many alternatives are available such as level-js
in the browser or memdown
for an in-memory store.
The level
module is the recommended way to get started. It offers a persistent database that works in Node.js and browsers. To store data in a different way you might like level-mem
for example, which exports the same API as level
but stores data in-memory. Visit Level/awesome
to discover more modules.
If you are new to Level, there is a quick answer: abstract-level
is the new core of Level on top of which several databases are (or will be) implemented. Read on if you're already familiar with Level modules (before 2022) and have used level
, levelup
, abstract-leveldown
, encoding-down
or deferred-leveldown
.
Back in 2012, levelup
offered a Node.js binding for Google's LevelDB. Authored by Rod Vagg, levelup
exposed the features of LevelDB in a Node.js-friendly way. It had streams, binary support, encodings... all the goodies. Later on, the binding was moved to leveldown
, so that other stores could be swapped in while retaining the friendly API of levelup
.
This is when "up" vs "down" naming was born, where databases followed the formula of "level = levelup + leveldown". For example, level-mem
was a convenience package that bundled levelup
with memdown
. The abstract-leveldown
module offered a lower-level abstraction for the "down" part, to encapsulate common logic between "down" stores. Many such stores were written, replacing LevelDB with IndexedDB, RocksDB, in-memory red-black trees, relational databases and more.
Around 2017, further parts were extracted from levelup
and moved to single-purpose modules. This effectively introduced the concept of "layers", where an implementation of abstract-leveldown
wasn't necessarily a storage for levelup
but could also wrap another abstract-leveldown
implementation. For example, levelup
encoding logic was extracted to encoding-down
. This changed the database formula to "level = levelup + encoding-down + leveldown". Or in other words: "levelup + layer + layer".
This highly modular architecture led to clean code, where each module had a single responsibility. By this time, the overall API had settled and matured, some contributors moved on to other exciting things and the primary remaining effort was maintenance. This posed new challenges. We worked on test suites, added automated browser tests, code coverage and database manifests.
Yet, releases too often required canary testing in dependents. It was hard to predict the effect of a change. In addition, documentation became fragmented and some modules actually suffered from the high modularity, having to peel off layers to customize behavior. At the same time, we could see that typical usage of a Level database still involved encodings and the other goodies that the original levelup
had.
Enter abstract-level
. This module merges levelup
, encoding-down
and abstract-leveldown
into a single codebase. There is more to say, but abstract-level
is a work in progress that hasn't yet proven itself, so we'll end here for now. Stay tuned!
This section will explain how to replace old modules (that are based on levelup
and abstract-leveldown
) with new abstract-level
based modules. At the time of writing, no abstract-level
implementation has been published yet.
If you need help - technical, philosophical or other - feel free to open an issue in community
or a more specific repository. We don't (yet) use GitHub Discussions, at least until discussions get the ability to close them.
You will generally find someone willing to help. Good questions get better and quicker answers. We do not offer paid support. All time is volunteered.
Most if not all activity happens on GitHub. See our project board to find out what we're working on. Any timelines there are just a rough indication of priority. We cannot guarantee that feature X or Y will actually be released on the given dates.
Subscribe to individual repositories to follow their progress. All releases are accompanied by a changelog and a GitHub Release, which gives you the option to only subscribe to new releases.
- @finnp - Finn Pauls
- @juliangruber - Julian Gruber
- @mafintosh - Mathias Buus
- @mcollina - Matteo Collina
- @MeirionHughes - Meirion Hughes
- @peakji - Yichao 'Peak' Ji
- @ralphtheninja - Lars-Magnus Skog
- @Raynos - Jake Verbaten
- @rvagg - Rod Vagg
- @vweevers - Vincent Weevers
- @brycebaril - Bryce Baril
- @chesles - j chesley
- @chjj - Christopher Jeffrey (JJ)
- @cjihrig - Colin Ihrig
- @deanlandolt - Dean Landolt
- @dominictarr - Dominic Tarr
- @emeryrose - Emery Rose Hall
- @eugeneware - Eugene Ware
- @filoozom - Philippe Schommers
- @heapwolf - Paolo Fragomeni
- @huan - Huan (李卓桓)
- @jameskyburz - James Kyburz
- @jcrugzz - Jarrett Cruger
- @kesla - David Björklund
- @maxogden - Max Ogden
- @No9 - Anton Whalley
- @nolanlawson - Nolan Lawson
- @obastemur - Oguz Bastemur
- @pgte - Pedro Teixeira
- @soldair - Ryan Day
- @substack - James Halliday
- @a0viedo - Alejandro Oviedo
- @abliss - Adam Bliss
- @achingbrain - Alex Potsides
- @adityapurwa - Aditya Purwa
- @agentilela - Alex Gentile
- @alessioalex - Alexandru Vlăduţu
- @andrewrk - Andrew Kelley
- @ArtskydJ - Joseph Dykstra
- @bewest - Ben West
- @bigeasy - Alan Gutierrez
- @braydonf - Braydon Fuller
- @calvinmetcalf - Calvin Metcalf
- @chiguireitor - Chiguireitor
- @cronopio - Daniel Aristizabal
- @danielravina - Daniel Ravina
- @dcousens - Daniel Cousens
- @deian - Deian Stefan
- @dey-dey - Amadeus J
- @diasdavid - David Dias
- @doowb - Brian Woodward
- @emschwartz - Evan Schwartz
- @fanatid - Kirill Fomichev
- @farskipper - Matthew Wright
- @Gawen - Gawen Arab
- @ggreer - Geoff Greer
- @ghostbar - Jose-Luis Rivas
- @guybrush - Patrick
- @hansott - Hans Ott
- @hden - Haokang Den
- @heavyk - kenny
- @ivantm - Ivan Miskovic
- @jamesgrayling - James Grayling
- @jfromaniello - José F. Romaniello
- @JimLiu - Jim Liu
- @joyeecheung - Joyee Cheung
- @kemitchell - Kyle Mitchell
- @kessler - Yaniv Kessler
- @kumavis - kumavis
- @kytwb - Amine Mouafik
- @l1x - Istvan
- @luandro - Luandro
- @mateodelnorte - Matt Walters
- @marcooliveira - Marco Oliveira
- @mcavage - Mark Cavage
- @mhart - Michael Hart
- @michaelnisi - Michael Nisi
- @monkeywithacupcake - jess
- @montyanderson - Monty Anderson
- @mscdex - mscdex
- @NickNaso - Nicola Del Gobbo
- @nrw - Nicholas Westlake
- @PascalTemel - Pascal Temel
- @pra85 - Prayag Verma
- @pskupinski - Preston Skupinski
- @qbit - Aaron Bieber
- @qs44 - Josh
- @raboof - Arnout Engelen
- @rasmuserik - RasmusErik Voel Jensen
- @refset - Jeremy Taylor
- @rh0 - Ryan Oles
- @RichardLitt - Richard Littauer
- @ryanramage - Ryan Ramage
- @sorribas - Eduardo Sorribas
- @sandfox - James Butler
- @sandersn - Nathan Shively-Sanders
- @seriousManual - Manuel Ernst
- @shama - Kyle Robinson Young
- @sharvil - Sharvil Nanavati
- @staltz - André Staltz
- @Tapppi - Tapani Moilanen
- @TehShrike - Josh Duff
- @thebergamo - Marcos Vinicius Bérgamo
- @thefoxis - Karolina Szczur
- @thlorenz - Thorsten Lorenz
- @timkuijsten - Tim Kuijsten
- @timoxley - Tim Oxley
- @vjrantal - Ville Rantala
- @watson - Thomas Watson
- @wbolster - wouter bolsterlee
- @willwhite - Will White
- @wolfeidau - Mark Wolfe
- @yoshuawuyts - Yoshua Wuyts
- @zixia - Huan LI
Is your name missing? Send us a pull request!
This repository also used to hold a small amount of metadata on past and present contributors. They can be accessed from code by:
console.log(require('level-community'))
This metadata is no longer maintained and the npm package will be deprecated at some point. Contributors are instead documented in this README under People.
Level/community
is an OPEN Open Source Project. This means that:
Individuals making significant and valuable contributions are given commit-access to the project to contribute as they see fit. This project is more like an open wiki than a standard guarded open source project.
See the Contribution Guide for more details.
Support us with a monthly donation on Open Collective and help us continue our work.