← All articles

JavaScript in an open-source database fills specific SQL gaps

JavaScript in an open-source database fills specific SQL gaps

JavaScript in the open-source relational database used by many web applications is being positioned as a narrowly defined extension to SQL, not as a way to relocate an application into the database. Percona described the approach on October 15, 2026, following demonstrations at Percona Live Europe 2026 of a JavaScript language component, a V8-based engine for Percona’s open-source database server 8.4. V8 is the software engine that executes JavaScript in Chrome and Node.js.

The distinction matters because database administrators have good reasons to distrust application logic embedded in databases. Large collections of stored procedures, reusable programs executed by a database, can become difficult to test, version, assign to an owner or distribute across multiple servers. Percona's proposed boundary is that SQL, the language used to query relational databases, handles sets of rows while JavaScript handles an individual value or a tightly bounded calculation.

The runtime enforces part of that boundary. A routine created with the JavaScript language component has no network access, cannot use network request methods or sockets, and cannot contact a payment provider or microservice. It has no file-system access, cannot read configuration files or keys, and does not provide Node.js or browser DOM APIs. There is no module-loading function, process interface or npm package ecosystem, and execution is synchronous rather than usefully asynchronous. Those restrictions prevent the routine from operating like a conventional application service.

Instead, JavaScript functions can be called from data-retrieval, table-combination, filtering and grouping clauses or from a trigger, which is database code that runs automatically when specified data changes. Percona's example key-normalisation function recursively walks a JSON document, converts object keys to lowercase and returns the transformed value. JSON is a structured text format for objects and lists. The function is declared as using the JavaScript language and as deterministic without issuing SQL, meaning the same input should produce the same output without running SQL or creating external side effects.

The intended targets are operations SQL cannot express conveniently. These include recursively examining JSON whose structure is not known in advance, since the JSON table facility requires paths to be written explicitly; algorithms requiring arrays, which SQL does not provide as a native type; and calculations exceeding the large-integer type's 19-digit limit, such as an IBAN mod-97 checksum using a 29-digit number. Other examples include iterative calculations involving aggregates, because a recursive CTE cannot contain an aggregate or window function and returns error number 3575, and richer text handling than basic uppercase or lowercase functions, such as preserving the capital D in McDonald. A recursive CTE is a query that repeatedly uses its own previous result.

Four demonstrations illustrated the same division of work. JSON key normalization reduced one partner report from 51 lines and four combined query branches to 19 lines without embedding partner names. In an input-validation demonstration, functions formatted names, email addresses and telephone numbers, checked an IBAN and assembled cleaned contact data. They identified problems in 460 of 2,000 rows and returned a list of errors for each affected row. The database could reject dirty input consistently, but the choice to correct, quarantine or follow up on a rejected contact remained an application decision.

The deduplication demonstration used Levenshtein distance, a count of the single-character edits needed to turn one string into another. Comparing 3,000 existing customers with 2,000 sign-ups would create six million possible pairs. SQL predicates based on city and initials first reduced that set to 21,352 pairs, and only those candidates reached the JavaScript distance function. In Percona's demo results, exact name matching found 21.7% of duplicates, while SQL filtering combined with two distance calculations found about 80% at 99.7% precision. The function produced a score; whether two customer records should be merged remained outside the database.

A geographic calculation showed the potential cost of repeatedly moving between a procedural SQL layer and the query executor. SQL window functions converted 44,347 raw travel stops into 16,232 weighted endpoints. JavaScript then ran the inner loop of a Weiszfeld procedure to find a geometric median, after which ordinary joins mapped the coordinate to a district. Percona reported 11.00 seconds and 327,033 statements for procedural SQL, compared with 0.52 seconds and six statements for JavaScript. One procedure call read 16,232 rows and wrote 2,000 answers without transferring result rows over the network. Percona attributes the improvement to avoiding 327,033 executor crossings, not to JavaScript inherently being faster.

That geographic demo used the session SQL interface, which means it currently runs on the enterprise edition of the database server. SQL execution from JavaScript was described as the leading roadmap item for Percona Server. In the present component, JSON columns are passed as native JavaScript objects, which can avoid separate parsing, but routines should still receive only the rows they need. The deduplication example demonstrates why filtering first is essential: invoking a custom function across every possible pair would discard SQL's strength at narrowing large datasets.

Percona proposes five tests for deciding whether code belongs in a database routine. It should operate on values already stored by the database, be deterministic and free of effects outside the transaction, be invoked by SQL, reduce the amount of data returned or avoid a network round trip, and implement a rule every client must follow. Validation, parsing, checksums, similarity scores, JSON reshaping and the inner loop of a numeric calculation can meet those tests. Workflows, approvals, notifications, authentication, user sessions, external API calls and frequently changing product policies belong in the application. A need for configuration tables, feature flags or another system is a warning that a routine has crossed that line.

There are operational controls as well. Developers can submit the function together with the SQL that calls it, while database administrators review its filtering and expected invocation count. The JavaScript routine creation privilege is required in addition to the routine creation privilege, allowing permission to write JavaScript routines to be granted explicitly. Routine definitions should be kept in version control beside schema migrations, and deterministic functions without hidden state can be tested with ordinary unit-testing methods.

Also available in: DeutschItaliano