Persevere and CouchDB are both new JSON-based storage systems, and have been receiving increasing focus. It may be informative to those interested in these new technologies to discuss the differences between these new database systems and what types of applications each is best suited for. While Persevere and CouchDB share an extremely similar JSON HTTP/REST interface and object structured data storage, there are important distinctions. Each of these different tools has a different target audience, and despite my obvious bias being the developer of Persevere, I hope to give at least some semi-objective differentiations between these tools.

Fundamentally, CouchDB is primarily focused on being a general purpose database that is an alternative to a relational database. Persevere encompasses data storage but focuses on Ajax applications, being a complete server-side data storage and application server for JavaScript-based web applications with tight integration with JavaScript. As such, Persevere might also be comparable to other JavaScript servers like Jaxer and Helma, and the distinction between these are worth noting as well. Here is a quick high-level comparison of the primary architectural focus of these different projects:

Project Description/Primary Use Case
CouchDB A JSON document based database for storing hierarchical object-style data structures using an HTTP interface with ACID lockless operation. This is primarily intended for being used by server-side technologies, and is not focused on direct browser access.
Persevere A JSON database integrated with a JavaScript environment for object persistence with HTTP interface for RESTful data interchange and RPC triggered code execution with Comet capabilities. Persevere is focused on browser-based client-UI-driven applications that utilize a web-based data and service oriented architecture between the browser and server. Persevere is built for data-centric Ajax/JavaScript-based applications with end-to-end JavaScript/JSON.
Helma Helma is a JavaScript server that also features a JavaScript environment with an object-oriented database for automatic data persistence. However, Helma differs from Persevere in that it is focused on a server-side MVC pattern and user interface generation instead of Persevere’s focus of enabling data access for rich browser-based clients.
Jaxer Jaxer is JavaScript server that is focused on recreating the browser’s API and environment (essentially running Firefox on the server) so that browser’s technologies can be utilized for server-side user interface generation. Since Jaxer allows server-side code to act like it’s in a browser, it can actually be used as a front-end for Persevere.

We will now take more in-depth look at the differences between Persevere and CouchDB (focusing on CouchDB due to it’s similarity to Persevere and its popularity).

Querying

An essential aspect of any database is its querying capabilities, and Persevere is differentiated from CouchDB by its ability to handle ad-hoc parameterized queries. Traditional relational databases utilize SQL for querying. SQL is inappropriate for a JSON-based database, the data structures are completely different, and for Ajax applications that are leveraging a HTTP interface directly from the browser, SQL is hopelessly insecure. CouchDB uses a view model which acts as an ongoing incremental map-reduce function, providing a constantly updated view of the database. From the HTTP interface different views can be accessed and data can be retrieved by key/index as well. The view model is well-suited for statically definable queries; job-style operations. On the other hand, Persevere uses JSONQuery, an extended version of JSONPath, as its query language which can be used to retrieve data from the database directly in the HTTP/REST interface. The difference here is that you can dynamically create a query with any arbitrarily complex expressions and any values. The workhorse of most applications is parametrized queries and these can easily be created with JSONQuery expressions and handled by Persevere.

Server-Side JavaScript Integration

Persevere is designed from the ground-up to have a consistent JavaScript to database integration. There is no need for object-relational mapping (ORM) layers, data is stored in the same structure that it is represented in JavaScript. The JavaScript environment has full orthogonal persistence capabilities. Data can updated by simply modifying properties with standard JavaScript syntax. Tables have corresponding JavaScript classes and every object in the table is treated as an instance of the class. Every class/table can have its own set of methods that are accessible as methods on the instance objects. For example, we can load an instance from a table in the JavaScript environment:

// create a new object in a table/class
var myObj = new MyClass();
// set a property, automatically persisted to the database
myObj.foo = "bar";
// this will return true
myObj instanceof MyClass 

Furthermore, you can also interact with these JavaScript methods through JSON-RPC calls. Thus client code can remotely execute server-side methods with direct integration with the data model. CouchDB does have a server-side JavaScript environment, but it is intended to be used to delegate map-reduce function processing, and is not available for server side RPCs, nor supports JavaScript class/table integration.

Security

Security and access control have been key features of Persevere from the start of the project; CouchDB also recently added access control. CouchDB provides two global access levels: Administrator and Reader. Persevere provides much finer-grained access control, it is possible to assign different access levels for different users to different tables, and even to different specific objects. Persevere’s security system is capability-based, and capabilities can be created that encompass a set of access levels to different objects or tables in the system. These capabilities can be individually granted to different users. CouchDB and Persevere both also support more programmatic control of security during object validation to handle more complex logic for access decisions.

Persevere provides an API for authentication from the web, and supports maintaining authentication with cookies (no manual manipulation of the requests is required).

Rich Data Structures

Both CouchDB and Persevere utilize JSON as the representation for data transfer and storage. However, Persevere also supports additional extensions of JSON for more complex data structures. Persevere utilizes JSON referencing to describe data structures with circular references, multiple references to single objects, cross-table references, and even remote URL references. Persevere additionally supports several JavaScript constructs that are not included in the JSON subset (JSON is a subset of JavaScript) including dates, functions, and NaN. Consequently, Persevere is designed to handle persisting virtually any data structure that can be created in a JavaScript environment.

Schema

CouchDB is explicitly schema-free, and no constraints are applied to documents. Persevere provides a flexible evolutionary approach to schemas, tables start schema-free, but schema constraints can be applied as desired to existing tables to create integrity guarantees. Partial constraints (to some properties) can be defined and modified at any point in time allowing any level of flexibility or integrity desired.

Scalability

Scalability and clustering has been one of the primary focuses of CouchDB: its name is an acronym for Cluster of Unreliable Commodity Hardware. CouchDB is certainly more mature in this category with its advanced clustering capabilities and heavy focus on extreme scalability. Clustering is certainly on the road map for Persevere. The REST architecture is designed for scaling across multiple machines and Persevere is well suited for adding this capability. In fact, with Persevere’s Comet notification system, clustering can and should be implemented almost entirely with its standard documented HTTP interface.

Comet Capabilities

With Persevere, it is possible to have a real-time view of data by subscribing to objects and receiving notification of changes. This capability is specifically designed for web applications. Notifications can be received from the browser using the REST Channels Comet interface. Persevere’s Comet capabilities are not limited to data changes, but any type of method call can serve as event for broadcast to clients. Persevere also supports Bayeux and its PubSub system. These Comet capabilities are exclusive to Persevere, and CouchDB has nothing that is similar.

Concurrency

Persevere and CouchDB both provide isolated transactions with lockless operation (objects are never locked). With CouchDB, each request corresponds to a single transaction, and by default Persevere behaves the same way. Persevere and CouchDB both support multi-operation transactions, and it is also possible to do multiple actions in one isolated transaction. For example, you could create a new object, update another object, and delete a third and then commit all three actions as a single transactional operation. CouchDB provides this capability through “bulk updates”. Persevere handles multiple action transactions by allowing multiple HTTP requests to be grouped together in a single transaction.

CouchDB provides the advantage of full ACID compliance. Persevere currently provides consistency, isolation, and durability, but is not truly atomic at this time. True atomicity is intended to be implemented in the future.

All object updates in CouchDB are preconditioned on providing the correct previous version number of the object that is being modified (optimistic concurrency). If the version number does not match, it is assumed to have been modified elsewhere and the operation will fail. Persevere provides a more flexible precondition system. Updates to objects can be made without preconditions to make it easier to get started. Preconditions can then be added, and any type of expression can be used as a precondition. In many situations predicating an update on a version number is a naive. Often an update is performed on the basis of various other, possibly more complex, object states. For example, if one is operating a translation service in order to translate text from English to Japanese, the application may wish to update the Japanese object on the precondition that the English version has not changed (rather than on the condition of the Japanese object not changing).

Cross-Domain Transports

From the browser, cross-domain requests require special techniques due to the same-origin policy that is applied to the XMLHttpRequest object. Persevere supports both JSONP (scripts with callbacks) and the window.name protocol for providing data for cross-domain web clients. CouchDB does not provide a facility for handling cross-domain requests.

Legacy Data Sources

Another unique capability of Persevere is that it will not only work with the default internal object database, but it can also be used to connect to existing SQL databases and even other remote RESTful HTTP servers as well. The configuration files are treated as data sources in the pluggable data source layer as well.

Binary/non-JSON Content Support

Both Persevere and CouchDB support the storage of non-JSON content in their databases. CouchDB treats non-JSON data as “attachments” within the JSON structure. On the other hand, Persevere provides a “File” table which holds the non-JSON entities, and with Persevere’s referencing capabilities, these entities can easily be included within any object in the system. Persevere builds on the REST architecture and allows these files to be used as an alternate representation of existing JSON objects. Content negotiation can then be used to retrieve these alternate format types for resources in Persevere. For example, one could define a JPEG image as an alternaten representation of a Person object in Persevere. To further support browser-based interactivity, Persevere supports the upload of files using standard browser forms. Files can be added and retrieved directly from browser.

Summary

Persevere and CouchDB’s JSON-based approach to database design is an exciting new avenue for data storage. CouchDB provides a compelling alternative to the relational database. Persevere’s leverages the JSON-based design to provide storage that is completely consistent with the object model used in the browser’s JavaScript environment, making it the perfect server for rich web applications based on a REST architecture, maintaining the REST principal of separating UI on the client-side from data storage on the server-side, and facilitating JavaScript based applications with uniform JavaScript/JSON data modeling from the client to the server.