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
  • Manually check for flag updates
  • Subscribing to flag updates
  1. SDK Reference

Getting flag updates

By default, SDKs check for updates to your flag logic in the background. When you save and activate a new commit from the Hypertune UI, SDKs will fetch your new flag logic and use it on the next flag evaluation.

You can change the frequency at which the SDK checks for updates by setting initDataRefreshIntervalMs in your createSource options:

src/lib/getHypertune.ts
import { createSource } from "../generated/hypertune";

const hypertuneSource = createSource({
  token: process.env.HYPERTUNE_TOKEN!,
  initDataRefreshIntervalMs: 5_000,
});

export default async function getHypertune() {
  // Get flag updates in serverless environments
  // await hypertuneSource.initIfNeeded();

  return hypertuneSource.root({
    args: {
      context: {
        environment:
          process.env.NODE_ENV === "development"
            ? "development"
            : "production",
        user: { id: "1", name: "Test", email: "hi@test.com" },
      },
    },
  });
}
src/components/AppHypertuneProvider.tsx
import { HypertuneProvider } from "../generated/hypertune.react";

export default function AppHypertuneProvider({
  children,
}: {
  children: React.ReactNode;
}) {
  return (
    <HypertuneProvider
      createSourceOptions={{
        token: import.meta.env.VITE_HYPERTUNE_TOKEN!,
        initDataRefreshIntervalMs: 5_000,
      }}
      rootArgs={{
        context: {
          environment:
            process.env.NODE_ENV === "development"
              ? "development"
              : "production",
          user: { id: "1", name: "Test", email: "hi@test.com" },
        },
      }}
    >
      {children}
    </HypertuneProvider>
  );
}
import generated.hypertune as hypertune

root_node = hypertune.create_source(
    init_data_refresh_interval_ms=5_000
).root({
    "context": {
        "environment": "development",
        "user": {
            "id": "test_id",
            "name": "Test",
            "email": "hi@test.com",
        }
    }
})
root_node.wait_for_initialization()
use hypertune::CreateOptions;

mod hypertune;

fn main() {
    let root_node = hypertune::initialize_hypertune(
        hypertune::VariableValues {},
        Some(CreateOptions {
            init_data_refresh_interval_ms: 5_000,
            ..Default::default()
        })
    )
    .unwrap()
    .root(hypertune::RootArgs {
        context: hypertune::Context {
            environment: hypertune::Environment::DEVELOPMENT,
            user: hypertune::User {
                id: "test_id".to_string(),
                name: "Test".to_string(),
                email: "test@test.com".to_string(),
            },
        },
    });
    root_node.wait_for_initialization();
}
package main

import (
	"fmt"
	"log"
	"os"
	"time"

	sdk "github.com/hypertunehq/hypertune-go"
	// Update to your project path.
	"github.com/myTeam/myProject/pkg/hypertune"
)

func main() {
	var token = os.Getenv("HYPERTUNE_TOKEN")
	source, err := hypertune.CreateSource(
		&token,
		sdk.WithInitDataRefreshInterval(5*time.Second),
	)
	if err != nil {
		panic(err)
	}
	defer source.Close()
	
	source.WaitForInitialization()
	
	rootNode := source.Root(hypertune.RootArgs{
		Context: hypertune.Context{
			Environment: hypertune.Development,
			User: hypertune.User{
				Id:         "test_id",
				Name:       "Test",
				Email:      "hi@test.com",
			},
		},
	})
}

You can disable checking for updates by setting the shouldRefreshInitData option to false:

src/lib/getHypertune.ts
import { createSource } from "../generated/hypertune";

const hypertuneSource = createSource({
  token: process.env.HYPERTUNE_TOKEN!,
  shouldRefreshInitData: false,
});

export default async function getHypertune() {
  // Get flag updates in serverless environments
  // await hypertuneSource.initIfNeeded();

  return hypertuneSource.root({
    args: {
      context: {
        environment:
          process.env.NODE_ENV === "development"
            ? "development"
            : "production",
        user: { id: "1", name: "Test", email: "hi@test.com" },
      },
    },
  });
}
src/components/AppHypertuneProvider.tsx
import { HypertuneProvider } from "../generated/hypertune.react";

export default function AppHypertuneProvider({
  children,
}: {
  children: React.ReactNode;
}) {
  return (
    <HypertuneProvider
      createSourceOptions={{
        token: import.meta.env.VITE_HYPERTUNE_TOKEN!,
        shouldRefreshInitData: false,
      }}
      rootArgs={{
        context: {
          environment:
            process.env.NODE_ENV === "development"
              ? "development"
              : "production",
          user: { id: "1", name: "Test", email: "hi@test.com" },
        },
      }}
    >
      {children}
    </HypertuneProvider>
  );
}
import generated.hypertune as hypertune

root_node = hypertune.create_source(
    init_data_refresh_interval_ms=0
).root({
    "context": {
        "environment": "development",
        "user": {
            "id": "test_id",
            "name": "Test",
            "email": "hi@test.com",
        }
    }
})
root_node.wait_for_initialization()
use hypertune::CreateOptions;

mod hypertune;

fn main() {
    let root_node = hypertune::initialize_hypertune(
        hypertune::VariableValues {},
        Some(CreateOptions {
            init_data_refresh_interval_ms: 0,
            ..Default::default()
        })
    )
    .unwrap()
    .root(hypertune::RootArgs {
        context: hypertune::Context {
            environment: hypertune::Environment::DEVELOPMENT,
            user: hypertune::User {
                id: "test_id".to_string(),
                name: "Test".to_string(),
                email: "test@test.com".to_string(),
            },
        },
    });
    root_node.wait_for_initialization();
}
package main

import (
	"fmt"
	"log"
	"os"

	sdk "github.com/hypertunehq/hypertune-go"
	// Update to your project path.
	"github.com/myTeam/myProject/pkg/hypertune"
)

func main() {
	var token = os.Getenv("HYPERTUNE_TOKEN")
	source, err := hypertune.CreateSource(
		&token,
		sdk.WithInitDataRefreshInterval(0),
	)
	if err != nil {
		panic(err)
	}
	defer source.Close()
	
	source.WaitForInitialization()
	
	rootNode := source.Root(hypertune.RootArgs{
		Context: hypertune.Context{
			Environment: hypertune.Development,
			User: hypertune.User{
				Id:         "test_id",
				Name:       "Test",
				Email:      "hi@test.com",
			},
		},
	})
}

Manually check for flag updates

You can manually check for flag updates with the initIfNeeded method:

import { createSource } from "../generated/hypertune";

const hypertuneSource = createSource({
  token: process.env.HYPERTUNE_TOKEN!,
  initDataRefreshIntervalMs: 5_000,
});

export default async function getHypertune() {
  await hypertuneSource.initIfNeeded(); // Check for flag updates

  return hypertuneSource.root({
    args: {
      context: {
        environment:
          process.env.NODE_ENV === "development"
            ? "development"
            : "production",
        user: { id: "1", name: "Test", email: "hi@test.com" },
      },
    },
  });
}

When using initIfNeeded, the initDataRefreshIntervalMs option specifies the minimum time between initialization requests.

For example, if you set this to 5_000, initIfNeeded will only trigger a new initialization request if the last one was over 5 seconds ago.

So you can await initIfNeeded on every backend request to ensure flag values are fresh while minimizing network latency and bandwidth.

Subscribing to flag updates

You can add and remove listeners to be notified of updates with:

hypertune.addUpdateListener(listener: (newStateHash: string) => void)
hypertune.removeUpdateListener(listener: (newStateHash: string) => void)

You can also get the current state hash with:

hypertune.getStateHash(): string | null
PreviousRemote loggingNextServerless environments

Last updated 2 months ago

This is particularly useful in like Vercel deployments, Cloudflare Workers, AWS Lambdas, etc, where background SDK tasks like fetching updates aren't guaranteed to execute.

serverless and edge environments