Reduction

Internally, Hypertune reduces your flag logic given a GraphQL query. You can try it out in the Preview view of the UI.

For example, given the schema:

type Query {
  root(context: Context!): Root!
}

input Context {
  user: User!
}

input User {
  id: String!
  name: String!
  email: String!
}

type Root {
  showNewEditor: Boolean!
}

And logic:

Query {
  root: ({ context }) => Root {
    showNewEditor: ({}) =>
      if (
        context.user.id in ["user_123", "user_456"] AND
        context.user.email endsWith "@test.com"
      ) {
        true
      } else {
        false
      }
  }
}

If the reducer is given the GraphQL query:

query TestQuery {
  root(
    context: {
      user: {
        id: "user_123"
        name: "Test"
        email: "test@test.com"
      }
    }
  ) {
    showNewEditor
  }
}

It will reduce the logic to:

Query {
  root: Root {
    showNewEditor: true
  }
}

This logic is fully reduced, i.e. in normal form, and so can be evaluated into JSON:

{
  "__typename": "Query",
  "root": {
    "__typename": "Root",
    "showNewEditor": false
  }
}

Partial reduction

You don't have to provide all of the field arguments in your GraphQL query. The reducer will reduce your logic as much as possible given the arguments you do provide.

For the schema and logic in the example above, if the reducer is given the GraphQL query:

query TestQuery {
  root(
    context: {
      user: {
        id: "user_123"
      }
    }
  ) {
    showNewEditor
  }
}

It will reduce the logic to:

Query {
  root: ({ context }) => Root {
    showNewEditor: ({}) =>
      if (true AND context.user.email endsWith "@test.com") {
        true
      } else {
        false
      }
  }
}

Note that the condition that references context.user.id has been evaluated and replaced with true but the condition that references context.user.email is still there as the query did not provide that argument.

This logic is partially reduced and so cannot be evaluated into JSON. It must be further reduced first.

Partial reduction is useful during SDK initialization.

Last updated