Axiom provides a fresh new look at web applications. Today, when building a web application, application providers are responsible for everything. They are responsible for implementing correct business logic, responsible for providing good performance, scalability and availability. They are also responsible for defining and implementing a privacy policy ensuring that private user data remains private.

Axiom is a web platform. It is intended to be provided as a service, and handle most of the common concerns in a web application: Scalability, availability and even confidentiality of user data. Application providers upload their business logic to Axiom as logic rules, written in Clojure. Actually, the rules are written in a Clojure DSL we call Cloudlog.

Cloudlog is a purely-declarative DSL, based on a purely-declarative subset of Clojure. Being purely declarative is important for two reasons:

  1. It keeps the application developer focused on defining the app's business logic rather than implementing it; and

  2. It makes sure the application cannot remember user data. This is important to make Axiom itself responsible for the confidentiality of user data.

This example demonstrates how an application is defined using Axiom. This is a Twitter-like application named tweetlog. Like Twitter, its main purpose is to show user timelines based on tweets made by users they follow.

In this example, we use two macros: defrule and defclause to define rules and clauses respectively.

Rules and clauses both represent logic deductions (similar to Horn Clauses in Prolog). Both rules and clauses operate on facts, which represent user data (:tweetlog/follows and :tweetlog/tweeted in our example).

Both rules and clauses can leverage the power of Clojure through the use of guards. Guards are pieces of Clojure code providing variable bindings and filtering through Clojure forms such as (for), (let) and (when). In our example we use guards to extract user-handles mentioned in tweets.

The key difference between rules and clauses is the fact that the logic of a clause is applied at query time, when the target query is already known, while the logic of a rule is applied at update time, as facts are added or removed.

This example is described is a demo we gave at <Programming> 2017.

Axiom uses a framework named Permacode to store Clojure source files comprising application definitions in the form of a Merkle Tree. Each version of each source file is assigned a hash code, which represents it within Axiom. Data derived from rules is placed in tables which names are prifixed by these hashes. This allows several versions of the same application to co-exist.

Since rules generate derived data, when introducing a new (version of a) rule, all derived data based on existing raw data and the new rule need to be generated. Axiom does that in bach processing, where different tables are considered one by one, but the data of each table is processed in parallel.

This form of automatic data migration frees application developers from the need to develop one-time migration scripts to transform data.

Once data migration is complete, an Apache Storm topology it launched to handle continous traffic. New facts are published on an AMQP topic, and Storm Spouts listen to them, and introduce them to the topology. Storm Bolts listen to these changes and cross-reference them with facts and partial rules that are stored in a database. The resulting partial rules and derived facts are stored to the database, and the derived facts are also published on AMQP topics. This allows them to be considered by other rules.

Clauses use a similar mechanism to rules, but their data is transient and is not stored to a database.

Please feel free to contact us for more information.