Pick BASIC,
compiled to native code.
mvx is a MultiValue system built with today's tools. An LLVM compiler turns your BASIC into real machine code with a real debugger. It ships as containers, and it keeps your data in PostgreSQL, MongoDB or a local store, whichever your team already runs.
Or try it now, with nothing to install but Docker:
docker run --rm -it ghcr.io/mvx-lang/mvx-demo Your records, in the database you already run.
Every file in an account is bound to a storage driver, and one account can mix them. The dictionary you already have becomes the schema. Programs keep reading and writing records, while reporting tools read the same live data as rows or documents. There is no export and no nightly copy.
Acme CorpþWidgetýGadgetþ2ý1þ999ý450 In the account
One record. þ separates attributes, ý separates values.
001 Acme Corp 002 WidgetýGadget 003 2ý1 004 999ý450
PRICE is MD2, so 999 is $9.99.
On PostgreSQL
The record is a jsonb document. Mapping adds typed columns, and the line items go in a child table.
| id | doc | CUSTOMER |
|---|---|---|
| \x3130303432 | {"1": "Acme Corp", …} | Acme Corp |
| id | seq | PRODUCT | QTY | PRICE |
|---|---|---|---|---|
| \x3130303432 | 1 | Widget | 2 | 9.99 |
| \x3130303432 | 2 | Gadget | 1 | 4.50 |
PRICE is a real numeric column, so sum("PRICE") works.
On MongoDB
One document. The mapped fields sit beside the record, and the line items become an array.
{
_id: Binary('MTAwNDI=', 0),
doc: { '1': 'Acme Corp', '2': [ … ], … },
CUSTOMER: 'Acme Corp',
ORDERITEMS: [
{ PRODUCT: 'Widget', QTY: '2', PRICE: 9.99 },
{ PRODUCT: 'Gadget', QTY: '1', PRICE: 4.50 }
]
} _id is the record id 10042, stored as bytes.
Three commands to put a file on PostgreSQL.
Define a connection once and bind files to it by name. The host and password live outside the account, so the account can go under version control and a container can supply its target through environment variables.
CREATE-MAP names the fields you want as columns. From then on every
WRITE keeps them up to date, changing only what moved.
> SET-CONNECTION pgmain driver=postgres address=db:5432 dbname=mvx user=app namespace=sales
> CREATE-FILE ORDERS USING @pgmain
> CREATE-MAP ORDERS CUSTOMER PRODUCT QTY PRICE SELECT id, doc->>'1' AS customer, doc->'2' AS products
FROM sales."ORDERS";
id | customer | products
--------+-----------+----------------------
\x3130303432 | Acme Corp | ["Widget", "Gadget"] SELECT o."CUSTOMER", sum(i."QTY"::numeric * i."PRICE") AS total
FROM sales."ORDERS" o
JOIN sales."ORDERS_ORDERITEMS" i USING (id)
GROUP BY o."CUSTOMER";
CUSTOMER | total
-----------+-------
Acme Corp | 24.48 use sales
db.ORDERS.aggregate([
{ $unwind: '$ORDERITEMS' },
{ $group: {
_id: '$CUSTOMER',
total: { $sum: { $multiply: [
{ $toInt: '$ORDERITEMS.QTY' }, '$ORDERITEMS.PRICE' ] } }
} }
])
[ { _id: 'Acme Corp', total: 24.48 } ] Pick a backend per file.
- SQLite
- The default for a new account. One file, nothing to run.
- PostgreSQL
- Records as jsonb, typed columns from your dictionaries, native indexes, and record locks shared across processes.
- MongoDB
- A document per record, mapped fields beside it, and associations as embedded arrays.
- MySQL and MariaDB
- The same document shape, on the database many shops already run.
- LMDB
- Embedded and very fast, for a single host.
- mvx-lmdbd
- LMDB behind a network daemon, so many hosts share one set of files.
- Directory files
- Each record is a plain OS file, so source code sits where git and your editor can see it.
Queries are pushed down to the database where it can answer them, so a LIST with a
WITH clause returns only the matching records rather than the whole table.
How the drivers work.
Compiled, not interpreted.
mvx compiles BASIC straight to machine code through LLVM, the compiler toolkit behind clang and Swift. It does not translate to C first. Numeric variables become real integers and doubles, so arithmetic runs at the speed of C.
It is also designed for today's hardware. The classic MultiValue systems were built when memory was measured in megabytes, and saved every byte. mvx trades some of today's gigabytes for speed: it keeps an index into each dynamic array, so reading or writing any element takes a few nanoseconds, however long the array is.
The compiler also writes standard debug information mapped to your BASIC line numbers. gdb and lldb step through the program you wrote, and profilers such as perf and Instruments report time against your own source lines.
- mvx LLVM, native code 101% of C
- jBASE 6.2.1 with -O4 compiled through C 1.6% of C
- UniData 8.3 interpreted 0.5% of C
- OpenQM (ScarletDME) interpreted 0.3% of C
Each system is measured against C on its own machine, in September 2026 (jBASE in August). How these were measured.
Made to run in containers.
A session is an ordinary process, and a file can live on another machine. So an account can keep its programs local while its data sits on a shared database, and you add capacity by adding containers instead of buying a bigger server.
- Published images for
linux/amd64andlinux/arm64:ghcr.io/mvx-lang/mvx,mvx-lmdbdandmvx-demo. - Relocatable tarballs that find their own runtime and drivers. No environment variables to set.
- Connections from the environment. Set
MVXCONN_SALESDB_ADDRESSand the account follows, with no file to edit. - Operations you already know. Backups, replication and monitoring are handled by PostgreSQL or MongoDB, with the tools your team uses today.
A complete MultiValue system.
- TCL shell
- The classic command line, with its verbs written in BASIC and cataloged like any program.
- Dictionaries and queries
LIST,SELECTandSORTdriven by your dictionaries, with conversions, formats and select lists.- Secondary indexes
- Built on the backend itself where it has them.
- Packages
MVPKGinstalls libraries from packages.mvx-lang.org, with dependencies resolved for you.- Version control
- Records, dictionaries and VOC under git, from the
GITverb or the shell. - Permissions in the runtime
- Restricted, developer and unrestricted sessions, enforced where a program cannot get around them.
Latest release
Relocatable builds for Linux. Installing mvx also installs MVPKG and git, and asks which version of each you want. Other packages are on packages.mvx-lang.org.
Released 17 September 2026
- Download for Linux x86-64 mvx-lang-0.2.2-linux-amd64.tar.gz, 25 MB
- Download for Linux ARM64 mvx-lang-0.2.2-linux-arm64.tar.gz, 21 MB
Checked against GitHub on 17 September 2026. This page is rebuilt when a new release is published.
tar xzf mvx-lang-0.2.2-linux-amd64.tar.gz # or -arm64
./mvx-lang/bin/mvx -a myaccount Documentation
- Getting started Build, install and open your first account.
- The language MVX BASIC, statements and intrinsic functions.
- TCL The command shell and its verbs.
- Files and dictionaries Records, dictionaries, queries, indexes, and mapping to SQL and JSON.
- Deployment Storage drivers, named connections, PostgreSQL and MongoDB.
- Containers The published images and how to run them.
- Packages Installing and publishing with MVPKG.
- Version control Hash-file records under git.
Have a Pick application?
mvx gets better by running real software. If you have a UniVerse, UniData, jBASE, D3 or Reality application, or a framework such as SB+ or CueBic, that you would let me test against, I would like to hear from you. I'm happy to sign an NDA.