Speed

Two of these take a second. One takes minutes, and it isn't us.

Every number on this page is produced by a project that ships with Neuridion, on your own Mac, when you press the button. Nothing here is a claim you have to take on trust — it is a benchmark you can run.

Run < 1 s

Your project starts in the IDE. No packaging, no signing — the window is just there.

Debug < 1 s

Same start, with breakpoints, step over, values you can open, and a query log that makes an N+1 loop visible.

Test build ~ 1–2 s

A real .app you can double-click. A 160-table project measured at about a second; the finished bundle was 12 MB holding a million records.

Release build 2–15 min

The striped part is Apple. Assembling, encrypting and signing is seconds; then the notarisation service has to look at it, and that queue is out of everyone's hands. You do this when you ship — not fifty times an afternoon.

“Nothing is compiled” — which is half true, so here is the whole of it.

A finished application is a precompiled shell — the same binary for everyone, built and signed by us once — with your project beside it as an encrypted payload. Building copies, encrypts and signs. Nothing of yours goes through a compiler, which is why the loop is instant and why a bug we fix in the runtime is fixed in every app you rebuild afterwards.

But your scripts are not interpreted line by line either. They run in JavaScriptCore — the engine inside Safari — which compiles hot code to native machine instructions while it runs. A loop that matters gets faster the second time round, without you doing anything. So: no build step, and no interpreter tax on the code that counts.

Honest small print: the first pass through a loop is the slow one, so a benchmark that times a cold loop against a warm one measures nothing. Ours runs each measurement three times and keeps the median.

Build — Harbour Supply (release)
  1. Harbour Supply.app assembled 0.4 s
  2. Starting data collected — 2 tables 0.2 s
  3. Project encrypted into the application 0.3 s
  4. Icon generated at every size 0.1 s
  5. Signed with Developer ID, Hardened Runtime 0.6 s
  6. Submitted to Apple for notarisation …waiting on Apple
  7. Ticket stapled
  8. Packaged
  9. Done — Harbour Supply-1.0.dmg
0.11 sOpening a 160-table project in the IDE
12 MBFinished app holding a million records
~18,000/sRows written straight through the session
< 2 sCold launch of that same app

And the server, flooded on purpose

We hammered one MacBook Air (M2) with hundreds of real clients at once over Wi-Fi, no pauses between requests. A safe number to plan around is about 50 clients at once — answers well inside a tenth of a second, on a plateau near 700 requests a second, with zero errors and not one refused connection. How far it really goes depends on what you build and how hard each client works the server — a form that reads one record is not a report that scans a table. Its own time per request stays in the low single-digit milliseconds, so the rest is the network, not the machine. Pushed far past that it slows down, it does not fall over: still answering, still in order.

The honest scale: a real office is dozens of people making a request every few seconds — a hundredth of this. Plan for a busy hundred; the hundreds beyond are headroom. How Client/Server works.

The server status window under load

Don't take our word for it

The same numbers, measured — and the one that explains the whole thing.

These come out of the Benchmark project that ships with Neuridion. It is one of the two examples in the box: open it, press the button, watch it measure your own Mac. Every figure below is the median of three runs.

The first pass through code
800 separate functions, each called once
2.3 M ops/s
Code that runs often
the same work, the loop kept warm
48 M ops/s

21× faster, and nobody did anything. That is the honest answer to “is it interpreted?” — it starts interpreted and stops being interpreted where it matters. JavaScriptCore watches which code is actually hot and compiles that to native machine instructions while your application runs. A rule that fires once on a button click is in the top row and nobody can tell; the loop over four thousand invoice lines is in the bottom one.

MeasuredPer secondWhat it means
The language
Reading a property of an object73,600,000rechnung.betrag, over and over
Calling a function68,200,000your own helpers cost nothing worth measuring
Building text11,600,000names, addresses, a line for a report
Sorting an array5,700,000elements per second, in memory
The bridge between JavaScript and the data
Reading a field of a record1,036,000this is the number that decides whether a synchronous API can work at all
Writing a field of a record851,000same crossing, the other way
The database
Finding one record by its identifier727,000the commonest thing any application does
Following a relationship480,000rechnung.kunde — one hop
Searching an indexed field42,000the same search, with and without an index — 14× apart, which is why the schema asks
Searching a field with no index3,100
Full-text search6,900real indexed search against a plain “contains” — 6× apart, and it ranks the answers as well
“contains” over the same text1,100
Counting and summing6,900whole-table totals, done by the database, not by loading rows

Measured on an Apple M3 Pro, macOS 26.5, median of three runs, spread under 5% on every line shown. Four measurements are deliberately left out — the bulk insert and delete figures scattered by more than 100% between runs on this machine, and a number that unreliable is not a number, whichever direction it happens to flatter. They are in the Benchmark project if you want to see them anyway.