Skip to content

Go SDK Guide

This guide covers adding Liteguard to a Go application.


Prerequisites

  • A Project Client Token from your Liteguard project. Follow the Getting Started guide through the Copy a Project Client Token step if you do not have one yet.
  • Go 1.21 or later.

Install the SDK

bash
go get github.com/liteguard/liteguard

Initialize the client

Create a Client during application startup and shut it down when the process exits.

go
package main

import (
    "context"
    "log"
    "os"

    "github.com/liteguard/liteguard"
)

func main() {
    client, err := liteguard.NewClient(os.Getenv("LITEGUARD_TOKEN"), nil)
    if err != nil {
        log.Fatal(err)
    }
    defer client.Shutdown()

    // ...
}

NewClient fetches the initial bundle before returning, so the client is ready to evaluate guards immediately.

Do not commit your token to source control. Read it from an environment variable or secrets manager.

Environment

go
client, err := liteguard.NewClient(
    os.Getenv("LITEGUARD_TOKEN"),
    &liteguard.ClientOptions{
        Environment: os.Getenv("LITEGUARD_ENV"),
    },
)

The slug must match one of the environments defined in your workspace. Slugs are visible in Config > Workspace > [your workspace] under Environments.


Evaluate a guard

client.IsOpen(ctx, guardName) reads from the locally cached bundle. No network call occurs per check.

go
if client.IsOpen(ctx, "payments.checkout") {
    // guarded code path
}

Passing properties

Attach a properties map to the context using liteguard.AddProperties. Any call to IsOpen in the same request can then be evaluated against those properties:

go
func handleCheckout(w http.ResponseWriter, r *http.Request) {
    ctx := liteguard.AddProperties(r.Context(), map[string]any{
        "user_id": userID,
        "plan":    plan,
    })

    if client.IsOpen(ctx, "payments.checkout") {
        // guarded code path
    }
}

Properties attached to the context are merged into the evaluation scope. Call AddProperties again to extend or override the current set.

Scopes

For finer control, create an explicit scope with a fixed set of properties:

go
scope := client.CreateScope(map[string]any{
    "user_id": userID,
    "plan":    plan,
})

if scope.IsOpen(ctx, "payments.checkout") {
    pass
}

if scope.IsOpen(ctx, "billing.invoice_download") {
    pass
}

Scopes do not read from the context properties, so they give a predictable, isolated evaluation surface.

Detailed decisions

Use client.Evaluate when you need the full decision object, such as a rate limit remaining count or the rule that matched:

go
decision, err := client.Evaluate(ctx, "payments.checkout")
if err != nil {
    // handle
}
if decision.IsOpen {
    // guarded code path
}

Shut down cleanly

Shutdown() flushes buffered telemetry and stops background goroutines:

go
defer client.Shutdown()

Pair Shutdown with a signal handler for long-lived servers:

go
sigs := make(chan os.Signal, 1)
signal.Notify(sigs, syscall.SIGTERM, syscall.SIGINT)
go func() {
    <-sigs
    client.Shutdown()
    os.Exit(0)
}()

Verify in Liteguard

After calling IsOpen at least once, open the Guards tab and confirm your guard appears. See Your First Guard to configure its behavior.


Next steps