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 ​