Hypertune
  • Introduction
  • Getting Started
    • Set up Hypertune
    • Next.js (App Router) quickstart
    • Next.js (Pages Router) quickstart
    • React quickstart
    • Remix quickstart
    • Gatsby quickstart
    • Vue quickstart
    • Nuxt quickstart
    • Node.js quickstart
    • React Native quickstart
    • JavaScript quickstart
    • Python quickstart
    • Rust quickstart
    • Go quickstart
    • Web quickstart
    • GraphQL quickstart
  • Example apps
    • Next.js and Vercel example app
  • Concepts
    • Architecture
    • Project
    • Schema
    • Flag lifecycle
    • Logic
    • Variables
    • Splits
    • A/B tests
    • Staged rollouts
    • Multivariate tests
    • Machine learning loops
    • Events
    • Funnels
    • Hypertune Edge
    • Reduction
    • SDKs
    • GraphQL API
    • Git-style version control
    • App configuration
  • Use Cases
    • Feature flags and A/B testing
    • Landing page optimization
    • In-app content management
    • Pricing plan management
    • Permissions, rules and limits
    • Optimizing magic numbers
    • Backend configuration
    • Product analytics
  • Integrations
    • Vercel Edge Config integration
    • Google Analytics integration
    • Segment integration
    • Webhooks
      • Creating webhooks
      • Handling webhooks
  • SDK Reference
    • Installation
    • Type-safe client generation
    • Initialization
    • Build-time logic snapshot
    • Hard-coded fallbacks
    • Local-only, offline mode
    • Hydrate from your own server
    • Wait for server initialization
    • Provide targeting attributes
    • Local, synchronous evaluation
    • Remote logging
    • Getting flag updates
    • Serverless environments
    • Vercel Edge Config
    • Custom logging
    • Shutting down
Powered by GitBook
On this page
  1. Concepts

Reduction

PreviousHypertune EdgeNextSDKs

Last updated 10 months ago

Internally, Hypertune reduces your flag 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 .

logic
SDK initialization