Moving to the Neo4j Query API


If you’re interested in transitioning to the Query API, this post will provide an overview of the key areas to consider and plan for. A follow-up post will dive deeper with an example. While there’s no immediate pressure to move from the HTTP API, it’s important to note that updates will be limited to critical security and defect fixes. All future development efforts will be focused on the Query API.

Embracing Differences

When designing the Query API, our primary goal was to make developer outcomes easier to achieve. As we iterated along the design and development process, it quickly became apparent that changes would be needed to realize the benefits we set out to achieve, and they would be breaking changes. Let ‘s delve into those changes and what they mean to you.

URL Paths

The most obvious change is seen when examining the Query API URL. The path has changed to support versioning and includes the API name. The latter avoids a namespace collision to allow the running of both APIs — something you’d want to do as part of a gradual migration process.

  • HTTP API: /db/{db name}
  • Query API: /db/{db name}/query/v2

Versioning

The Query API supports the current version (n) and the immediately prior one (n-1). This allows for any future breaking changes while ensuring that applications continue without interruption. It also clearly identifies which Query API variant is being used. Following in the well-worn steps of best practices, the version number is now in the URL like so:

/db/{db name}/query/v{major version number}

Using Implicit and Explicit Transactions

Like the HTTP API, the Query API offers implicit and explicit transactions. For the former, you supply a Cypher statement, and the transaction is managed for you. With the latter, you’re in control of the transaction from start to finish.

The HTTP API path for these operations is somewhat shy when it comes to showing intent. From the paths below, which does what?

  • URL path: /db/{db name}/query/v{major version number}/tx
  • URL path: /db/{db name}/query/v{major version number}/tx/commit

You would use the top one for explicit and the bottom for implicit — something that’s not immediately obvious.

We‘ve taken advantage of the association of ‘tx’ with transactions for the Query API URL paths:

  • Implicit URL path: /db/{db name}/query/v{major version number}
  • Explicit URL path: /db/{db name}/query/v{major version number}/tx

One Cypher Statement Per Request

On the face of it, having multiple Cypher statements in a single request has advantages; you get a lot done in one go and only take the hit from establishing a TCP connection once. However, this also resulted in challenges in tracking down a Cypher statement with a syntax error (not working as intended). With the vast majority of programming platforms allowing the re-use of an existing TCP session — eliminating the time overhead of connection establishment — the advantages of many Cypher statements in a single request have faded away.

It became clear that the simplicity offered from a single Cypher statement per request was the direction of travel to pursue. This also created the opportunity to improve error information and to make better use of HTTP status codes.

Response Notifications Now Have a Category

This is an addition in the Notification section of a response and is there for classification purposes (i.e., performance). This is primarily intended for logging and subsequent analysis.

JSON With Type Information

JSON allows several for these types: string, number, JSON object, array, Boolean, or null. The Neo4j type list is much more extensive. In an attempt to bring these together, the HTTP API has a content type known as JOLT, which is a mashup of JSON and Bolt Protocol (the packet stream-based protocol used by Neo4j server and platform drivers).

In all honesty, the feedback from developers for JOLT can best be summarized as “Would not recommend,” but there remained a desire for the inclusion of type information.

We commenced on a ground-up redesign for extending JSON with Neo4j type information and making it available with the Query API. You now add to your request header:-

Accept: application/vnd.neo4j.query

This will result in a JSON response decorated with Neo4j type information. If you’ve been using HTTP JOLT, this is something to dive into. More detail on this is available in the JSON with type documentation. Feedback is welcome.

Response Changes

It’s morphed a bit from the response from the HTTP API. The Query API JSON response can have one or more of these top-level entries:

{
"data":{},
"counters":[],
"profiledQueryPlan": {},
"identifiers":[],
"children":[],
"notifications":[{}],
"errors":[{}],
"bookmarks": []
}

The entry returned will depend on the request itself, if an error occurred, feedback information from the Neo4j server, and if the Cypher statement was to be profiled. Details for each of these are available in the documentation.

What’s Next?

When planning your migration, there are three other items for consideration:

  • Be curious. Although this blog has covered the main differences between the HTTP API and the Query API, don’t assume these are the only areas you need to pay attention to. These are general points, and each application will have its quirks. Be curious. Go read your application source code to learn more about HTTP API usage.
  • Remember that the tortoise won. “The Tortoise and the Hare” is one of Aesop’s Fables where the hare loses the race due to foolish overconfidence. A slow and steady migration is better than a hasty swap-over. For self-managed customers, the HTTP API will be supported as part of Neo4j 5.26 LTS with updates for critical bugs and security defects (Aura customers have only had the Query API).
  • Dual-running. Take advantage of running both the HTTP API and Query API for back-to-back testing where results, performance, and security can be compared between the two. This also allows for a gradual transition where applications are incrementally moved to the Query API.
  • Read the docs. Remember to read the Query API documentation to learn what the API does and doesn’t do.

Happy moving!


Moving to the Neo4j Query API was originally published in Neo4j Developer Blog on Medium, where people are continuing the conversation by highlighting and responding to this story.