
- Subscribe to RSS Feed
- Mark as New
- Mark as Read
- Bookmark
- Subscribe
- Printer Friendly Page
- Report Inappropriate Content
GraphQL API's are quickly becoming my preferred way of exchanging data between UI Builder or Service Portal and the ServiceNow instance. For a long while, I've been a proponent of using Scripted REST APIs instead of using the SP Widget Server Script for heavier and more interactive front ends. Think front ends like ServiceNow's Workplace Reservations application. Having a reusable server API is great when you end up having to change front end frameworks to say... UI Builder.
So why is GraphQL overtaking Scripted REST API's for me? Performance and flexibility. Let's take a simple use case such as showing the user a list of Incident records. We might solve this with a Scripted REST API like the one below.
Scripted REST API Example:
(function process(/*RESTAPIRequest*/ request, /*RESTAPIResponse*/ response) {
let conditions = request.body.data.conditions;
let incidents = new GlideRecord('incident');
incidents.addEncodedQuery(conditions);
incidents.query();
let result = [];
while (incidents.next()) {
result.push({
sys_id: incidents.sys_id.toString(),
number: incidents.number.toString(),
short_description: incidents.short_description.toString(),
caller: {
sys_id: incidents.caller_id.sys_id.toString(),
name: incidents.caller_id.name.toString(),
email: incidents.caller_id.email.toString(),
},
assigned_to: {
sys_id: incidents.assigned_to.sys_id.toString(),
name: incidents.assigned_to.name.toString(),
email: incidents.assigned_to.email.toString(),
},
});
}
response.setBody(result);
})(request, response);
With GraphQL, we might solve the same issue with a custom API schema that looks like this one:
GraphQL Schema:
schema {
query: Query
}
type Query {
incidents(conditions: String): [Incident]
}
type Incident {
sysId: GlideElement @source(value: "sys_id")
number: GlideElement @source(value: "number")
shortDescription: GlideElement @source(value: "short_description")
caller: User @source(value: "caller_id.value")
assigned_to: User @source(value: "assigned_to.value")
}
type User {
sysId: GlideElement @source(value: "sys_id")
name: GlideElement @source(value: "name")
email: GlideElement @source(value: "email")
}
type GlideElement {
value: String! @source(value: "value")
displayValue: String! @source(value: "display_value")
}
Both allow you to get a list of incidents containing the same fields, so what's the difference?
REST is rigid, GraphQL is Flexible
The first difference is that REST will always return the same payload. It will always contain the same list of fields, at least in the example given. Want a compact view that only shows the number and short description? REST returns the whole payload. Want a view that doesn't include the assigned to? Too bad, you are getting that data anyway.
Now, you could implement some if statements and request parameters to yield different tailored payloads but you would have to know all of the different payloads you want up front. If one day you decide you need a different combination of fields, you would have to write new code for that.
On the other hand, the GraphQL schema above (with proper resolvers and resolver mappings) allows you to request any combination of those fields and nested fields. In GraphQL, the server describes what it CAN include in the payload, but the client decides what should be included in the payload. So, we could write a GraphQL query which returns a payload containing only the number and short description:
GraphQL query that returns only short description and number:
query {
snc {
GlideRecordQuery {
incidents {
shortDescription {
value
}
number {
value
}
}
}
}
}
But we could also write a query that includes the full payload:
GraphQL Query with all fields in the payload:
query {
snc {
GlideRecordQuery {
incidents {
sysId {
value
displayValue
}
number {
value
displayValue
}
shortDescription {
value
displayValue
}
caller {
sysId {
value
displayValue
}
name {
value
displayValue
}
email {
value
displayValue
}
}
assigned_to {
sysId {
value
displayValue
}
name {
value
displayValue
}
email {
value
displayValue
}
}
}
}
}
}
Both of these queries can be run on the exact same GraphQL API. Each query returns only the data and fields requested. So instead of needed one endpoint for the summary payload and another endpoint for the detailed payload, you can have one endpoint that can handle either request.
GraphQL runs only the queries it needs
This flexibility also grants a number of performance advantages to GraphQL. In REST endpoints, we usually take a kitchen sink approach to response payloads until performance dictates. In this case, we might include the Caller and Assigned To data in the payload just in case it's needed. The issue is that those two pieces of data include data that is dot-walked from the sys_user table. So that is two extra queries to the sys_user table. If we don't need that data, we could be slowing our page load or even the instance itself in some cases.
The GraphQL approach ensures that we don't execute queries or code for data that isn't requested. In this case, if you don't request the displayValue fields, then getDisplayValue() won't get called on those fields. If caller and assigned_to aren't included in the query, then there is no dot walk or query to the sys_user table. GraphQL is able to intelligently determine which resolver code needs to be executed and run the minimum required to get the desired result.
GraphQL is faster on the network
Additionally, GraphQL can often spend less time with open requests on the network compared to kitchen sink REST API's. First, since you get only the payload you need, payloads can often be smaller than what REST API's often provide. Second, GraphQL's support for nested types (such as dot-walking assigned to and caller data above) often makes it easier to request all of the data required for specific UI's in a single network call. In case you aren't familiar with the request waterfall, minimizing the number and size of network requests is extremely important for building high performance UI's.
Conclusion
It is important to acknowledge that the most optimized REST API may be able to beat out the most optimized GraphQL API. I haven't run the hard numbers on this one, but I acknowledge that GraphQL API's have to run code to route a query to the proper resolvers. That isn't free and REST API's don't have to do that. But on average, for the real-world implementations of Scripted REST API's vs GraphQL APIs, I prefer GraphQL in most scenarios. They get me closer to an optimized API with less effort.
And that's performance I can see.
- 3,452 Views
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.