Server SDK
Server-side SDK for Node.js backends and Next.js Server Components. Evaluate flags, track events, and manage identity from your server.
Installation
Add the package to your server project or Next.js app. It is separate from @sheepit-ai/react — install only what your environment needs.
pnpm add @sheepit-ai/serverInitialization
The server SDK requires a secret key (lp_sec_*). Never expose this key to the client or commit it to source control. Store it in an environment variable and read it at runtime.
Option 1: Direct initialization
Construct GoaTechServer directly. This is the portable option — works in any Node.js environment including AWS Lambda, Cloudflare Workers (with the edge runtime), and standalone Express/Fastify servers.
import { GoaTechServer } from "@sheepit-ai/server";
const gt = new GoaTechServer({
apiKey: process.env.GT_SECRET_KEY!,
environment: "production",
});Option 2: Next.js helper (recommended)
getGoaTech() returns a module-scoped singleton that reads configuration from environment variables automatically. Call it at the top of any Server Component or Route Handler — the instance is shared across requests, keeping memory usage low.
import { getGoaTech } from "@sheepit-ai/server/nextjs";
// Module-scoped singleton — reads from env vars:
// GT_SECRET_KEY, GT_ENVIRONMENT, GT_API_URL
const gt = getGoaTech();Methods
All evaluation methods are async and return a Promise. Tracking and identity methods are non-blocking — they enqueue the payload and return immediately. Use flush() or close() to ensure events are delivered before your process exits.
flag(flagKey, context?, defaultValue?)
Evaluates a feature flag server-side. Results are cached for the duration of cacheTtl (default 60 seconds) to avoid repeated network calls within the same deployment. Pass a context object with a userId and optional traits to enable user-level targeting rules.
const showBanner = await gt.flag("maintenance_banner", { userId: "user_123" }, false);
// With targeting context
const limit = await gt.flag(
"upload_limit",
{ userId: user.id, traits: { plan: "enterprise" } },
10
);experiment(experimentKey, userId)
Returns the experiment assignment for a given user as { variant: string; payload?: Record<string, unknown> }. If the user is not enrolled in the experiment, variant is "control". Unlike the client SDK, exposure is not tracked automatically — call track() with an exposure event if you need to record it.
const { variant, payload } = await gt.experiment("checkout_flow", userId);track(eventName, properties?, userId?)
Tracks a server-side event. Non-blocking — events are queued in-memory and flushed in batches according to flushInterval and flushSize. If the queue exceeds maxBufferSize, new events are dropped to prevent OOM conditions during prolonged flush failures.
gt.track("order_completed", { orderId: "ord_123", total: 99.99 }, userId);identify(userId, traits?)
Associates traits with a user in Sheepit. Call this after significant profile changes — plan upgrades, onboarding completion, role changes — so targeting rules reflect the latest state. Like track(), this is non-blocking.
gt.identify(userId, { email: user.email, plan: "pro", company: "Acme" });flush()
Force-flushes all queued events immediately. Returns a Promise that resolves once the batch has been delivered. Useful in serverless contexts where the process may be frozen before the next scheduled flush.
await gt.flush();close()
Graceful shutdown. Flushes all remaining events and cleans up internal timers. Call this in your process termination handler to avoid losing events during deployments or restarts.
// In your shutdown handler
process.on("SIGTERM", async () => {
await gt.close();
process.exit(0);
});Next.js Patterns
The server SDK is designed to work naturally with the Next.js App Router. Flag evaluation happens on the server before the page is streamed to the client, so users never see a flash of the wrong content.
Server Components
Call getGoaTech() and evaluate flags directly inside your async Server Component. The result is baked into the rendered HTML — no client-side JS needed for the flag decision.
// app/page.tsx (Server Component)
import { getGoaTech } from "@sheepit-ai/server/nextjs";
import { auth } from "@/lib/auth";
export default async function HomePage() {
const session = await auth();
const gt = getGoaTech();
const showPromo = await gt.flag(
"holiday_promo",
{ userId: session?.userId },
false
);
return (
<main>
{showPromo && <PromoBanner />}
<Hero />
</main>
);
}Route Handlers
Use the same getGoaTech() singleton in Route Handlers to branch server logic and track events tied to API operations.
// app/api/checkout/route.ts
import { getGoaTech } from "@sheepit-ai/server/nextjs";
export async function POST(req: Request) {
const gt = getGoaTech();
const { userId, items } = await req.json();
const { variant } = await gt.experiment("checkout_flow", userId);
gt.track("checkout_started", { variant, itemCount: items.length }, userId);
// ... process checkout
}Environment Variables
The getGoaTech() helper reads these variables from process.env automatically. Set them in .env.local for local development and in your hosting provider's secrets manager for production.
| Variable | Required | Default | Description |
|---|---|---|---|
GT_SECRET_KEY | Yes | — | Your secret API key (lp_sec_*). Never expose to clients. |
GT_ENVIRONMENT | No | "production" | Target environment. Use "development" or "staging" for non-production deployments. |
GT_API_URL | No | "https://api.goatech.ai" | Override for self-hosted or staging API instances. |
Configuration Reference
When constructing GoaTechServer directly, you can pass all options to the constructor. The same options are also accepted by a config file read by getGoaTech() — see the Configuration page for details.
| Option | Type | Default | Description |
|---|---|---|---|
apiKey | string | — | Secret key. Required. |
environment | string | "production" | Target environment. |
cacheTtl | number | 60_000 | Flag config cache TTL in milliseconds. |
flushInterval | number | 5_000 | Event flush interval in milliseconds. |
flushSize | number | 50 | Maximum events per flush batch. |
maxBufferSize | number | 10_000 | Maximum queued events. Events are dropped once this limit is reached to prevent OOM. |
debug | boolean | false | Enables verbose logging. Do not enable in production. |
const gt = new GoaTechServer({
apiKey: process.env.GT_SECRET_KEY!,
environment: "production",
cacheTtl: 60_000, // Flag config cache TTL (default: 60s)
flushInterval: 5_000, // Event flush interval (default: 5s)
flushSize: 50, // Events per batch (default: 50)
maxBufferSize: 10_000, // Max queued events before dropping (default: 10k)
debug: false, // Enable debug logging
});