# Backends
trilogy supports several different backends, each with its own advantages.
Because trilogy supports each of these equally, you can choose any one of them depending on which is the best fit for your project. And don't worry too much about choosing the right one the first time since you can change the backend at any time without affecting trilogy's behavior or changing any of your code.
# sqlite3
(opens new window)
const db = create('./storage.db', {
client: 'sqlite3'
})
// or, since this is the default:
const db = create('./storage.db')
This is the predominant native asynchronous SQLite binding for Node. If you're
looking for performance this is a good place to start, and is inherently async.
However since this is a native C++ module it is required to build this against
your runtime environment. In most cases a precompiled binary can be downloaded
by node-pre-gyp
(opens new window).
Using sqlite3
can sometimes be a hassle due to its C++ nature, gyp
, pre-gyp
,
Electron, different OS environments or architectures, Node versions, and so on
and so on. To help with situations where this is an issue trilogy also supports
a module that does not require native compilation toolchains.
# sql.js
(opens new window)
const db = create('./storage.db', {
client: 'sql.js'
})
sql.js
runs purely in JavaScript and has no native C++ dependency. On the
one hand, this means you can use it in almost any environment and will have no
trouble using it in the runtimes trilogy supports.
On the other hand this means performance likely isn't as stellar, and the queries are run synchronously. Synchronous vs asynchronous seems to be a matter of debate (opens new window) when it comes to Node's competing SQLite libraries, but trilogy normalizes both of these backends to Promises and you won't need to interact with them differently.
# memory-only
const db = create(':memory:')
Set the file path to exactly :memory:
to disable persistence and store your
database entirely in memory. None of the data will be saved across sessions,
but queries are blazing fast due to the lack of I/O.
In-memory storage is great for tests — trilogy itself uses this for its tests (example (opens new window)) — and for performance when persisting data isn't a requirement.
This is a SQLite feature supported by both of the above backends that you can read more about here (opens new window).
# so... which one?
Which one you choose is dependent on your target environments. It's recommended
to start with sqlite3
and build it as needed. If you face compatibility
issues that you'd rather not deal with, you can always switch to sql.js
with
no changes to the rest of your code - trilogy handles them both in the same way.
If you maintain a cross-platform Electron app, for example, you can use sql.js
and you won't need to deal with the problems that led to stories like
this (opens new window) or this (opens new window) or this (opens new window).
That last link describes the current best way to handle the native sqlite3
module in Electron — tools like electron-rebuild
(opens new window)
have reduced a lot of frustration in using the native sqlite3
module over
the sql.js
alternative.