restQL integrates seamlessly with your current microservice architecture.

There is no need for any implementation server side, just configure the service endpoints, run restQL server and start querying.

Why restQL?

A microservice-based architecture isn’t a silver bullet. Despite its immediate benefits to the service teams, it poses by its very nature a challenge in terms of complexity and performance to the consumers. restQL aims to solve this gap, reducing network round-trips and simplifying microservice orchestration.

There's a nice blog post explaining in more details restQL motivation, the challenges in building such solution and how it compares to Falcor and GraphQL: Tackling microservice query complexity.


restQL GraphQL Falcor
Codeless deploy V X X
No schema duplication V X X
Native browser caching V X X
CDN and Proxy caching V X X
Easy error and failure handling V X X
Available to all languages V V X
Battle tested in large deploys V V V

restQL acts as a bridge between the client and the backend services, so there's no need to duplicate the API schema or to code the backend integrations.

Also, restQL keeps HTTP semantics and by doing so inherit HTTP benefits such as browser native cache, CDN and proxy cache and easy error handling.

What can you do with restQL?

You can find below some restQL features and how they compare to a manual javascript implementation.

Parallel calls

restQL builds a dependency graph and will perform parallel invocations of the listed resources.

restQL

  from hero
      with
          name = "Restman"

  from villain
      with
          name = "SOAPLord"

javascript

    function loadData() {

      const heroPromise = loadHero({name: "Restman"})
      const villainPromise = loadVillain({name: "SOAPLord"})

      return Promise.all([heroPromise, villainPromise])
        .then(([hero, villain]) => ({
          hero: hero,
          villain: villain
        })

    }

Chained invocations

When you have a service that depends on an information from a previous service restQL will delay the execution of the second service until the first completes.

restQL

  from hero
      with
          name = "Restman"

  from sidekick
      with
          hero = hero.id

javascript

  function loadData() {

    const heroPromise = loadHero({name: "Restman"})

    const sidekickPromise = heroPromise.then(hero => 
                              loadSidekick({heroId: hero.id}))

    return Promise.all([heroPromise, sidekickPromise])
      .then(([hero, sidekick]) => ({
        hero: hero,
        sidekick: sidekick
      })

  }

Multiplexed invocations

Sometimes there's a need to retrieve a list from a service and then for each item from that list invoke another service. By default, restQL considers lists as multiplexed invocations and will make a request for each item.

restQL

  from search
      with
          role = "hero"

  from hero as heroes
      with
          name = search.results.name

javascript

  function loadData() {

    const searchPromise = loadSearch({role: "hero"})

    const heroesPromise = searchPromise.then(search => {
      const heroes = search.map(item => loadHero({name: item.name})
      return Promise.all(heroes)
    })

    return Promise.all([searchPromise, heroesPromise])
      .then(([search, heroes]) => ({
        search: search,
        heroes: heroes
      }))

  }

Filter

restQL allows to specify which fields should be fetched for each resource. This allows to reduce payload, which is critical to mobile clients.

restQL

    from heroes as hero
        with
            name = "restQL Master"
        only
            skills,
            name,
            archEnemy

Embed

It's possible to embed restQL directly into your application so you don't have to spin and manage an additional server. This is also an easy approach for parallel requests in Java.

Clojure

  (restql/execute-query 
    :mappings endpoints-map 
    :query "from hero with name = $name" :params { :name "Restman" } )/pre>
                    

Java

  RestQL restQL = new RestQL(config);
  restql.executeQuery("from user with name = ?", "Restman");
                    

JS

  var restlq = require('@b2wdigital/restql')

  // executeQuery(mappings, query, params, options) => <Promise>
  restql
    .executeQuery(
      {user: "http://your.api.url/users/:name"},
      "from user with name = $name",
      { name: "Duke Nukem" })
    .then(response => console.log(response))
    .catch(error => console.log(error))
                      

Manage

restQL Manager allows you to easily test new queries, save resources endpoints, check resources status and save queries that can be used by clients just by referencing the query's name.

Fork me on GitHub