Running JavaScript in Azure DocumentDB with Chakra

The Chakra JavaScript engine is well known for powering Microsoft Edge and Universal Windows Applications. Starting with Windows 8.1 and Windows Server 2012 R2, Chakra added a new set of embedding APIs (called JavaScript Runtime or JSRT APIs) that allow embedding Chakra outside of the above mentioned client-only scenarios.

Azure DocumentDB was one of the first services to embed Chakra to provide JavaScript programmability natively within the database engine. With the recent announcement that Microsoft has open-sourced core components of Chakra (called ChakraCore) on GitHub, we are happy to share our experience and future plans with Chakra.

Running JavaScript in a NoSQL database

At the heart of Azure DocumentDB is a write-optimized NoSQL document-oriented database engine which is purpose built to natively support JSON and JavaScript. Originating from JavaScript object expressions, JSON is a frequently used transport mechanism for structured and semi-structured data. DocumentDB uses Chakra to provide a server-side programming surface for the transactional execution of JavaScript logic natively inside the database engine. We believe the approach of using JavaScript as a modern day T-SQL provides developers with a natural interface to implement business logic expressed in the form of sever-side scripts (stored procedures, triggers and user-defined functions) in DocumentDB.

As a multi-tenant service, we have built the entire DocumentDB stack with resource governance and performance isolation from the ground up. All components, including DocumentDB’s database engine are designed to enforce resource governance very strictly. The DocumentDB engine requires each of the hosted components to live within an extremely frugal budget of system resources to deliver SLA-backed target performance. This meant that the JavaScript runtime also must support the same level of performance isolation and ability to deliver the required performance under stringent resource constraints. After evaluating several JavaScript engines, we eventually decided to use Chakra because it was able to meet all of our multi-tenancy requirements.

Let’s use stored procedures to look at how Chakra is used within DocumentDB. Developers can register and execute stored procedures, written in JavaScript, which can be used to perform a batch or sequence of operations across multiple documents as a single ACID transaction. When a tenant registers a stored procedure, it gets implicitly precompiled to bytecode by Chakra. When a tenant executes the stored procedure, the script gets executed on a Chakra runtime in a sandboxed environment. The runtime provides the tight integration of the JavaScript programming model on an isolated snapshot of the database. Upon successful completion of the stored procedure, all operations to the database are committed under a single transaction. If there is any exception propagated from within the script, DocumentDB will automatically roll back the entire transaction.

Let’s dig a little deeper in to a couple of the Chakra features we’re really excited about and how we use them to provide first-class JavaScript support within DocumentDB:

Rental threading - Chakra features a rental threading model where a JavaScript runtime is always single-threaded, but not hard-bound to a specific thread. In other words, a runtime only operates on one thread at a time, but its thread affinity is free to change from time to time. Rental threading works particularly well for DocumentDB because DocumentDB can manage a runtime pool and assign a runtime to each tenant to execute JavaScript. This avoids the cost of initiating a new runtime per tenant and allows DocumentDB to preserve security and isolation for each tenant.

Bytecode serialization - Upon registering a server-side script, DocumentDB uses Chakra to pre-compile and serialize the script to bytecode. In a normal JavaScript execution pipeline, the engine needs to parse the code, produce syntax trees and generate bytecode prior to execution. Chakra’s bytecode serialization allows DocumentDB to pre-process scripts up until (and including) bytecode generation and save a cached copy of the bytecode for re-use. This allows users to avoid the cost of re-parsing the script each time it is executed, which leads to substantial performance savings over time.

Chakra recently open-sourced its core components, codenamed ChakraCore. ChakraCore carries almost the same set of capabilities that Chakra has, and is shaped to be a standalone JavaScript engine that is being developed in the open going forward. DocumentDB is committed to migrating from Chakra to ChakraCore in the near future. By moving to ChakraCore, DocumentDB retains all the aforementioned benefits, and can provide its users with even more features. Now that Chakra has become open source, the DocumentDB team intends to contribute back changes as well.

Closing remarks

Relying on Chakra brought us great success and we’re excited about what will be made possible by migrating to ChakraCore. The embedding wiki is a good starting point to learn how to embed ChakraCore in to your own applications.

If you have feedback for the Chakra team you can open an issue on GitHub or reach them through Twitter, @ChakraCore.