Quick Start
This guide gets Pennant running locally and walks you through creating your first feature flag and evaluating it from an SDK.
Prerequisites
- Docker and Docker Compose (recommended), or Go 1.22+ with CGO enabled
Step 1: Clone and start
Open .env and set a strong secret (minimum 32 characters):
Then start:
The server is ready when you see:
Open http://localhost:8080 and log in with:
- Email:
admin@pennant.local - Password:
admin
Change the default password
The seeded admin password is public knowledge. Change it immediately via the dashboard Settings page before exposing Pennant on a network.
Step 2: Create your first flag
Via the dashboard
- In the sidebar, select the default project → production environment.
- Click New Flag.
- Set Key to
my-first-flag, Type toboolean, and toggle Enabled on. - Click Save.
Via the API
# 1. Get a JWT
TOKEN=$(curl -s -X POST http://localhost:8080/auth/login \
-H 'Content-Type: application/json' \
-d '{"email":"admin@pennant.local","password":"admin"}' \
| jq -r '.accessToken')
# 2. Create a flag
curl -X POST http://localhost:8080/api/v1/projects/default/environments/production/flags \
-H "Authorization: Bearer $TOKEN" \
-H 'Content-Type: application/json' \
-d '{
"key": "my-first-flag",
"name": "My First Flag",
"type": "boolean",
"enabled": true,
"defaultVariation": "on",
"variations": [
{"key": "on", "value": true},
{"key": "off", "value": false}
]
}'
Step 3: Evaluate the flag from your app
Go SDK
package main
import (
"context"
"fmt"
"log"
"pennant/sdk/go/pennant"
)
func main() {
client, err := pennant.NewClient(pennant.Config{
BaseURL: "http://localhost:8080",
SDKKey: "sdk-server-default-prod",
})
if err != nil {
log.Fatal(err)
}
defer client.Close()
ctx := pennant.EvalContext{Key: "user-123"}
enabled := client.BoolVariation("my-first-flag", ctx, false)
fmt.Printf("my-first-flag = %v\n", enabled)
}
TypeScript SDK
import { PennantClient } from "pennant-sdk";
const client = new PennantClient({
baseUrl: "http://localhost:8080",
sdkKey: "sdk-server-default-prod",
});
await client.connect();
const enabled = client.boolVariation("my-first-flag", { key: "user-123" }, false);
console.log("my-first-flag =", enabled);
Step 4: Add a targeting rule
Let's enable the flag only for users in the beta group.
curl -X PUT http://localhost:8080/api/v1/projects/default/environments/production/flags/my-first-flag \
-H "Authorization: Bearer $TOKEN" \
-H 'Content-Type: application/json' \
-d '{
"enabled": true,
"defaultVariation": "off",
"variations": [
{"key": "on", "value": true},
{"key": "off", "value": false}
],
"rules": [
{
"id": "rule-beta",
"clauses": [
{
"attribute": "group",
"op": "in",
"values": ["beta"]
}
],
"variation": "on"
}
]
}'
Now evaluate with a context that has the group attribute:
ctx := pennant.EvalContext{
Key: "user-123",
Attributes: map[string]any{"group": "beta"},
}
enabled := client.BoolVariation("my-first-flag", ctx, false)
// enabled == true
Next steps
- Configuration reference — all environment variables
- How evaluation works — priority order and bucketing
- A/B testing — run experiments and track metrics
- Go SDK guide — reconnect behavior, all variation types
- TypeScript SDK guide — BigInt bucketing, browser vs. server