> ## Documentation Index
> Fetch the complete documentation index at: https://docs.useshipd.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Migrate from environment variables

> Replace FEATURE_X environment variables with shipd flags, keeping the variable as the default during the switch.

## Overview

If you gate features with checks like `process.env.FEATURE_NEW_CHECKOUT === "true"`, each variable maps to a flag. In this guide you replace one with the boolean flag `new-checkout`, keep the variable as the SDK default while you migrate, then delete it.

## Map variables to flag types

| Environment variable | Flag |
| - | - |
| `FEATURE_NEW_CHECKOUT=true` | `type: "boolean"` → [`isEnabled`](/reference/sdk#isenabled) |
| `SEARCH_MODE=semantic` (fixed set of values) | `type: "variant"` → [`getVariant`](/reference/sdk#getvariant) |
| `MAX_RETRIES=3` | `type: "number"` → [`getNumber`](/reference/sdk#getnumber) |
| `CHECKOUT_CONFIG='{"mode":"strict"}'` | `type: "json"` → [`getJson`](/reference/sdk#getjson) |

Per-deploy values (`.env.staging`, `.env.production`) become per-environment **Fallthrough** values. Secrets and connection strings stay in environment variables.

## Steps

**1. Define the flag**

```ts TypeScript theme={null}
// shipd.config.ts
import { defineFlags } from "shipdit/config";

export default defineFlags({
  "new-checkout": {
    type: "boolean",
    default: false,
    description: "Replaces FEATURE_NEW_CHECKOUT",
  },
});
```

```go Go theme={null}
// Entry inside config.ShipdConfig (import github.com/alasti-company/useshipd.com/sdks/go/config).
"new-checkout": {Type: "boolean", Default: false,
    Description: "Replaces FEATURE_NEW_CHECKOUT"},
```

**2. Push it and match each environment**

```bash theme={null}
shipd push --project web-app --env production
```

For each environment where the variable is currently `true`, open the flag in the dashboard, select the environment, set **Fallthrough** to `true`, and click **Save environment**. Push sets **Fallthrough** in the environment you push to from `default`, and resets it on every push when they differ. If the environment you push to serves `true`, change `default` to `true` in `shipd.config.ts` (or run `shipd pull`) before your next push, or the push turns the flag off there. Other environments keep their dashboard value. See [Environments](/concepts/environments).

**3. Use the variable as the SDK default**

Until shipd serves the flag, the client falls back to `defaults`. Seed them from the variable so behavior doesn't change if the edge is unreachable during the switch:

```ts TypeScript theme={null}
// src/lib/shipd.ts
import { createClient } from "shipdit";
import type { FlagDefinitions } from "../generated/flags";

export const shipd = createClient<FlagDefinitions>({
  sdkKey: process.env.SHIPD_SDK_KEY!,
  defaults: {
    "new-checkout": process.env.FEATURE_NEW_CHECKOUT === "true",
  },
});

await shipd.ready();
```

```go Go theme={null}
// Initialize once at process startup. Imports: context, log, os, time, and shipd.
client, err := shipd.New(shipd.Options{
    SDKKey: os.Getenv("SHIPD_SDK_KEY"),
    Defaults: map[string]any{
        "new-checkout": os.Getenv("FEATURE_NEW_CHECKOUT") == "true",
    },
})
if err != nil { log.Fatal(err) }
defer func() {
    ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
    defer cancel()
    if err := client.Shutdown(ctx); err != nil { log.Printf("shipd events: %v", err) }
}()
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
if err := client.Ready(ctx); err != nil { log.Printf("using defaults: %v", err) }
cancel()
```

**4. Replace the checks**

```ts TypeScript theme={null}
// src/checkout.ts
// Before
if (process.env.FEATURE_NEW_CHECKOUT === "true") { /* … */ }

// After
if (shipd.isEnabled("new-checkout", { userId })) { /* … */ }
```

```go Go theme={null}
// Before
if os.Getenv("FEATURE_NEW_CHECKOUT") == "true" { /* ... */ }

// After
if client.IsEnabled("new-checkout", shipd.EvaluationContext{UserID: userID}) { /* ... */ }
```

**5. Remove the variable**

Once every deploy reads the flag, replace the default with a literal (`"new-checkout": false`) and delete `FEATURE_NEW_CHECKOUT` from your environments.

Now you can change the value without a redeploy, and [target users](/flags/targeting) or [roll out by percentage](/flags/percentage-rollouts).

For Go definition snippets, add the entries to `config.ShipdConfig` in `shipd.config.go` before pushing. See [Define flags in code](/config-as-code/define-flags#go-definitions).

## Related

* [Create a boolean flag](/flags/boolean)
* [Node.js SDK](/sdks/node)


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.