featureflags

package
v0.0.0-...-09b745a Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Nov 7, 2026 License: Apache-2.0 Imports: 35 Imported by: 27

README

LaunchDarkly client authentication

The client selects authentication in this order:

  1. A non-empty LAUNCH_DARKLY_API_KEY selects SDK-key authentication and ignores the OAuth variables.
  2. Without an SDK key, OAuth variables select OAuth client-credentials authentication. Incomplete OAuth configuration fails startup.
  3. Without either, the client uses the offline flag store.

For direct LaunchDarkly access, set LAUNCH_DARKLY_API_KEY. An optional LAUNCH_DARKLY_BASE_URL redirects streaming, polling, events, and diagnostics to a Relay proxy.

For an OAuth gateway, leave LAUNCH_DARKLY_API_KEY unset and configure:

Variable Value
LAUNCH_DARKLY_BASE_URL HTTPS gateway URL
LAUNCH_DARKLY_OAUTH_TOKEN_URL HTTPS OAuth token endpoint
LAUNCH_DARKLY_OAUTH_CLIENT_ID Deployment client ID
LAUNCH_DARKLY_OAUTH_CLIENT_SECRET Deployment client secret
LAUNCH_DARKLY_OAUTH_AUDIENCE Optional audience parameter for the token request

Use the existing deployment OAuth credentials and audience when the gateway accepts that identity. The token endpoint must support the client_credentials grant with credentials in the request body.

Both client constructors enable live flag updates without an SDK key in OAuth mode. OAuth URLs must not contain embedded credentials, query parameters, or fragments.

The client caches tokens and refreshes them before expiry. Every new HTTP request uses the current bearer token, including stream reconnections, events, and diagnostics. The gateway must bound stream duration because an open stream does not reauthenticate when its token expires.

Token requests have a five-second timeout. OAuth requests do not follow redirects. Authentication failures do not switch between SDK-key and OAuth modes.

The client mints its first token at startup. If the token endpoint answers with a non-5xx response, construction fails, including with WithStartOnInitTimeout. If the token endpoint is unreachable or returns 5xx, the SDK retries and the existing initialization timeout policy applies.

A gateway 401 or 403 before the gateway has accepted any request stops the SDK, as a rejected SDK key does. After the first accepted request, the client drops its cached token on 401 or 403 and the SDK retries with a fresh one. The SDK's own backoff bounds the retry and mint rate.

Documentation

Index

Constants

View Source
const (
	SandboxKind                        ldcontext.Kind = "sandbox"
	SandboxTemplateAttribute           string         = "template-id"
	SandboxKernelVersionAttribute      string         = "kernel-version"
	SandboxFirecrackerVersionAttribute string         = "firecracker-version"
	SandboxEnvdVersionAttribute        string         = "envd-version"
	// SandboxTypeAttribute distinguishes "sandbox" from "build" runs.
	SandboxTypeAttribute string = "sandbox-type"

	TeamKind             ldcontext.Kind = "team"
	UserKind             ldcontext.Kind = "user"
	ClusterKind          ldcontext.Kind = "cluster"
	BatcherKind          ldcontext.Kind = "batcher.name"
	InstanceGroupKind    ldcontext.Kind = "instance-group"
	ServiceKind          ldcontext.Kind = "service"
	TemplateKind         ldcontext.Kind = "template"
	VolumeKind           ldcontext.Kind = "volume"
	CompressFileTypeKind ldcontext.Kind = "compress-file-type"
	CompressUseCaseKind  ldcontext.Kind = "compress-use-case"

	// DeploymentEnvironmentKind has the same name and value as the
	// OpenTelemetry deployment.environment resource attribute, so a flag
	// rule and a dashboard filter select one place with one string.
	DeploymentEnvironmentKind ldcontext.Kind = "deployment_environment"
)

kinds

View Source
const (
	APIGroupRateLimitDisabled = "disabled"
	APIGroupRateLimitShadow   = "shadow"
	APIGroupRateLimitEnabled  = "enabled"
)
View Source
const (
	DefaultKernelVersion = "vmlinux-6.1.158"

	// DefaultEnvdVersion is the envd new template builds bake when neither the
	// build-envd-version flag nor DEFAULT_ENVD_VERSION says otherwise:
	// "promoted" selects the node-local promoted binary (HOST_ENVD_PATH), the
	// behavior every build has always had, so deployments without
	// LaunchDarkly (dev, self-host) are unaffected.
	DefaultEnvdVersion = "promoted"
)
View Source
const (
	DefaultFirecrackerV1_10Version = "v1.10.1_30cbb07"
	DefaultFirecrackerV1_12Version = "v1.12.1_210cbac"
	DefaultFirecrackerV1_14Version = "v1.14.1_431f1fc"
	// The v1.14-0 release line. 0.2.0 introduces the in-place checkpoint's
	// balloon reporting-pause API; filesystem-only snapshots ship with every
	// e2b release from 0.1.0 — the per-feature floors live in fcversion.
	DefaultFirecrackerV1_14_0Version = "v1.14-0.2.0"
	// The v1.17-0 release line: upstream Firecracker v1.17 with the v1.14-0
	// patches, and it restores snapshots taken by every older line. It starts
	// at 0.4.0 because e2b release numbers rise across lines and v1.14-0
	// already shipped 0.3.x; the version gates key on that number.
	DefaultFirecrackerV1_17_0Version = "v1.17-0.4.0"
	// New template builds get the current release; existing builds keep
	// resolving within their own line below (cross-line upgrades are an
	// operator decision via the firecracker-versions flag, never a baked
	// default — the map invariant key == LDKey(value) enforces it).
	DefaultFirecrackerVersion = DefaultFirecrackerV1_14_0Version
)

The Firecracker version per release line: legacy lines pin last-tag_short-SHA dev builds; e2b lines (vX.Y-<e2b-major>) pin releases published by the Publish fc-versions workflow. TODO: The short tag here has only 7 characters — the one from our build pipeline will likely have exactly 8 so this will break.

View Source
const (
	LogsWriteModePrimaryOnly      = "primary_only"
	LogsWriteModePrimaryAndShadow = "primary_and_shadow"
)

Log write routing modes for LogsWriteConfigFlag.

View Source
const FirecrackerVersionsEnv = "DEFAULT_FIRECRACKER_VERSIONS"

FirecrackerVersionsEnv overrides the firecracker-versions fallback where there is no LaunchDarkly: a JSON object of release line to served version, e.g. {"v1.14-0":"v1.14-0.3.1"}. Set it identically on every binary that resolves versions (api and orchestrator). Like the flag, an override may move a line onto another release, so one security fix can cover every line: {"v1.10":"v1.14-0.3.1","v1.12":"v1.14-0.3.1","v1.14":"v1.14-0.3.1","v1.14-0":"v1.14-0.3.1"}; the operator owns snapshot compatibility across that move.

View Source
const ReasonSourceStalled = "source_stalled"

ReasonSourceStalled is the no-upgrade reason for a resume whose candidate on the host mount did not answer in time: neither a misconfigured target nor a cold cache, but a slow or stuck mount, which clears on its own.

Variables

View Source
var (
	SnapshotFeatureFlag                 = NewBoolFlag("use-nfs-for-snapshots", env.IsDevelopment())
	TemplateFeatureFlag                 = NewBoolFlag("use-nfs-for-templates", env.IsDevelopment())
	EnableWriteThroughCacheFlag         = NewBoolFlag("write-to-cache-on-writes", false)
	UseNFSCacheForBuildingTemplatesFlag = NewBoolFlag("use-nfs-for-building-templates", env.IsDevelopment())
	CreateStorageCacheSpansFlag         = NewBoolFlag("create-storage-cache-spans", env.IsDevelopment())
	OrchAcceptsCombinedHostFlag         = NewBoolFlag("orch-accepts-combined-host", false)
	WorkspacesEnabledFlag               = NewBoolFlag("workspacesEnabled", false)

	// ClientProxyResumeParkingFlag lets client-proxy retry a wake-on-traffic
	// resume that failed retryably, read by each request at its own park
	// transition: off means the first retryable failure is that request's answer.
	ClientProxyResumeParkingFlag = NewBoolFlag("client-proxy-resume-parking", false)

	// FsFreezeViaExecFlag freezes the guest rootfs with `fsfreeze -f /` run through
	// the envd exec API before a filesystem-only pause, for guests whose envd
	// predates the native /fsfreeze endpoint. Off = those guests fall back to a
	// plain guest sync (today's behavior). Falls back to sync per-pause if the
	// guest lacks fsfreeze or the freeze fails.
	FsFreezeViaExecFlag = NewBoolFlag("fsfreeze-via-exec", false)

	// FsOnlyResumeAPIFlag accepts memory:false on resume/connect of a
	// memory-inclusive snapshot (an explicit cold-boot rescue). Off = the
	// request is rejected, never silently downgraded to a memory restore.
	FsOnlyResumeAPIFlag = NewBoolFlag("fs-only-resume-api", false)

	// PrebootFsRecoveryFlag runs a jailed filesystem recovery before every cold
	// boot of a rootfs that was not frozen at pause (fs_quiesced absent/false).
	// Separate from FsOnlyResumeAPIFlag because it also changes the behavior of
	// existing filesystem-only cold boots whose pause fell back to sync.
	PrebootFsRecoveryFlag = NewBoolFlag("preboot-fs-recovery", false)

	// StorageSoftDeleteCheckFlag enables reading the storage-index soft-delete
	// tombstone on header load (one extra GCS Attrs on cold load). Off = no overhead.
	StorageSoftDeleteCheckFlag = NewBoolFlag("storage-soft-delete-check", false)
	// StorageSoftDeleteEnforceFlag makes a soft-deleted object fail the read
	// (fail closed) instead of only emitting a metric + log. Requires the check flag.
	StorageSoftDeleteEnforceFlag = NewBoolFlag("storage-soft-delete-enforce", false)

	// UseMemFdFlag asks Firecracker to back guest memory with a memfd and
	// pass the fd over the UFFD socket; the orchestrator then mmaps it
	// directly instead of using process_vm_readv on pause.
	UseMemFdFlag = NewBoolFlag("use-memfd", true)

	// UseSyncWPFlag asks Firecracker (via use_sync_wp on snapshot load) to
	// register guest memory for SYNCHRONOUS userfault write-protect events,
	// which the orchestrator's serve loop resolves, instead of the kernel's
	// in-place WP_ASYNC clears. Foundation for the copy-on-write background
	// memory snapshot. Default off = WP_ASYNC, today's behavior. Enable only
	// where the deployed FC accepts the use_sync_wp field: FC rejects unknown
	// fields on snapshot load, so a mismatch fails the resume loudly.
	UseSyncWPFlag = NewBoolFlag("use-sync-wp", false)

	// UffdInstallDedupFlag makes the UFFD serve loop drop a MISSING fault for
	// a page another worker is already installing instead of starting a
	// second worker, buffer and source read for it (one installer per page).
	// Read once per start/resume. Off restores one worker per fault message,
	// the behaviour before the dedup; it is the kill switch for that change.
	// UFFD_INSTALL_DEDUP sets the fallback where there is no LaunchDarkly.
	UffdInstallDedupFlag = NewBoolFlag("uffd-install-dedup", envBoolOr("UFFD_INSTALL_DEDUP", true))

	// InPlaceCheckpointFlag makes Checkpoint pause, snapshot and resume the
	// SAME Firecracker process (in-place) instead of resuming a fresh sandbox
	// from the new build. Only honored for sandboxes resumed with
	// UseSyncWPFlag on: in-place skips the snapshot re-load that re-arms
	// write-protection, so dirty tracking across repeated checkpoints relies
	// on the sync-WP serve loop; resume-fresh stays the fallback for async
	// sandboxes and when this flag is off.
	InPlaceCheckpointFlag = NewBoolFlag("in-place-checkpoint", false)

	// GuestRebootInPlaceFlag boots a sandbox whose guest reset itself (a
	// reboot, or a kernel crash that restarts) again on its own disk and
	// network slot, under the same sandbox and execution IDs, instead of
	// stopping it. Read at the moment of the reset for a running sandbox, and
	// at the start of a create or resume for a reset before envd answers. The
	// fallback reads GUEST_REBOOT_IN_PLACE so a deployment without
	// LaunchDarkly can turn it on.
	GuestRebootInPlaceFlag = NewBoolFlag("guest-reboot-in-place", envBoolOr("GUEST_REBOOT_IN_PLACE", false))

	// GuestPowerOffEndFlag keeps a sandbox whose guest powered itself off,
	// disk included, and lists it as powered off, so the API ends it with the
	// sandbox's own timeout action: a kill, or a filesystem-only pause.
	// Read when a cold boot, or a restore whose guest profile asks for it,
	// decides whether to declare the ACPI power-off device, at an exit to
	// decide whether to wait for the final guest counters, and again at the
	// power-off. A process whose Firecracker took the device is held whatever
	// the flag says then, so turning it off never costs that sandbox its disk.
	// Off, a power-off of a process that did not take the device itself (a
	// restore that sent no declaration, even when its snapshot's guest still
	// has the device) stops the sandbox as a crash does.
	// The fallback reads GUEST_POWEROFF_END so a deployment without
	// LaunchDarkly can turn it on.
	GuestPowerOffEndFlag = NewBoolFlag("guest-poweroff-end", envBoolOr("GUEST_POWEROFF_END", false))

	// SandboxEndedOnNodeFlag lists a sandbox that ended on its node without
	// being asked to (a crash, a reset that was not booted again) as ended for
	// two minutes, so the API's sync ends its record with kill reason
	// ended_on_node instead of keeping it running until its end time. A held
	// power-off is listed under GuestPowerOffEndFlag whatever this says. Off,
	// an unrequested end leaves the record as it did before. The fallback
	// reads SANDBOX_ENDED_ON_NODE so a deployment without LaunchDarkly can
	// turn it on.
	SandboxEndedOnNodeFlag = NewBoolFlag("sandbox-ended-on-node", envBoolOr("SANDBOX_ENDED_ON_NODE", false))

	// FilesystemOnlyCheckpointFlag enables the filesystem-only checkpoint:
	// the rootfs is exported and no memfile, the SAME Firecracker process is
	// resumed afterwards, and a sandbox created from the build cold-boots.
	// Independent of InPlaceCheckpointFlag: no memory is exported, so the
	// sync-WP tracking, the Firecracker release and the balloon that gate the
	// memory in-place path play no part. Off (the default) refuses the
	// request before anything is touched; there is no memory fallback, since
	// the caller asked for a template that cold-boots.
	FilesystemOnlyCheckpointFlag = NewBoolFlag("filesystem-only-checkpoint", false)

	// EnvdInitHeldRequestFlag makes a start whose envd is at or above
	// utils.MinEnvdVersionForHeldInit wait on one /init for its whole envd-wait budget
	// instead of abandoning an attempt every envd-init-request-timeout-milliseconds, and
	// send that /init's body, timestamp included, only once envd asks for it
	// (Expect: 100-continue). Off (the default) runs today's retry loop on every start.
	EnvdInitHeldRequestFlag = NewBoolFlag("envd-init-held-request", false)

	// InPlaceCheckpointReportingFlag re-admits to the in-place checkpoint the
	// sandboxes whose balloon runs free-page reporting, and those whose
	// balloon could not be read. It only decides where DeferMemoryExportFlag
	// is on: there the CoW window pauses reporting and the deferred reports
	// drain onto the serve loop when it resumes, so off (the default) sends
	// both cohorts resume-fresh, and on lets them in place for a per-team A/B
	// of the two paths without a redeploy. Where the deferred export is off
	// the in-place checkpoint takes the synchronous copy, never touches
	// reporting, and every balloon goes in place regardless of this flag.
	InPlaceCheckpointReportingFlag = NewBoolFlag("in-place-checkpoint-reporting", false)

	// DeferMemoryExportFlag makes the in-place checkpoint export guest
	// memory through the CoW window instead of the synchronous dirty-RAM
	// copy: the dirty set is write-protect-armed while the VM is paused, the
	// guest resumes immediately, and pages are captured in the background
	// (first guest write to an uncaptured page copies the pre-image before
	// the write proceeds). Only takes effect on the in-place path with a
	// sync-WP UFFD backend. When the VM's balloon runs continuous free-page
	// REPORTING, reporting is PAUSED for the window's lifetime (a REMOVE
	// zapping an uncaptured page would export zeros where pause-time content
	// is owed); requires an FC build with /balloon/reporting — pause failures
	// fall back to the synchronous copy. (The synchronous pre-pause
	// free-page-hinting drain settles before the dirty readout and needs no
	// pause.) Default off = today's synchronous copy. Because of that pause,
	// this flag also moves the checkpoint ROUTE of reporting-built (and
	// unread-balloon) sandboxes: turning it on sends them resume-fresh unless
	// InPlaceCheckpointReportingFlag re-admits them, and turning it off
	// mid-ramp sends them back in place. The route panel and the checkpoint
	// counter's route label show the move.
	DeferMemoryExportFlag = NewBoolFlag("defer-memory-export", false)

	// SyncWPTrackerDirtyFlag derives the pause-time dirty set from the
	// orchestrator's page tracker (installs + synchronous WP-fault
	// promotions) instead of Firecracker's GetDirtyMemory pagemap scan,
	// skipping that RPC entirely. Only consulted for sandboxes resumed with
	// UseSyncWPFlag on — under WP_ASYNC the kernel clears protections
	// in-place and the tracker never sees guest writes. Evaluated fresh at
	// each pause, so flipping it off immediately reverts running sandboxes to
	// the pagemap source (kill switch). Burn-in gate before enabling: the
	// dirty-source divergence log (emitted while this flag is off) must
	// show pagemap_only == 0 for sync-WP sandboxes — a nonzero count means
	// the tracker missed a write and would corrupt the snapshot.
	SyncWPTrackerDirtyFlag = NewBoolFlag("sync-wp-tracker-dirty", false)

	// MemfdBackgroundCopyFlag streams the memfd into the snapshot cache on
	// a goroutine so Pause returns as soon as the diff metadata is written.
	// Only takes effect when UseMemFdFlag is also on.
	MemfdBackgroundCopyFlag = NewBoolFlag("memfd-background-copy", true)

	// MemfileDiffDedupFlag enables 4 KiB-page dedup of the memfile diff
	// against the base memfile. bestEffort skips uncached blocks; directIO
	// opens the dedup output with O_DIRECT. The remaining keys budget fetch
	// defragmentation of the deduped diff — fetchRunWindowPages is the
	// uncompressed frame/window size served per backing fetch — see
	// orchestrator block.DedupBudget for semantics (0 = disabled/default).
	MemfileDiffDedupFlag = NewJSONFlag("memfile-diff-dedup", ldvalue.FromJSONMarshal(map[string]any{
		"enabled":                        false,
		"bestEffort":                     false,
		"directIO":                       false,
		"maxFetchWindowsPerBlock":        0,
		"maxPromotedParentPagesPerBlock": 0,
		"maxPagesPerPromotedFrame":       0,
		"blockFaultPct":                  0,
		"fetchRunWindowPages":            0,
	}))

	// MemfdDedupInflightServeFlag lets a resume that overlaps an in-flight
	// memfile dedup serve dirty pages straight from the still-mapped memfd
	// instead of blocking until dedup finishes. It gates both windows: serving
	// via a provisional local header while dedup is still computing the deduped
	// header, and serving during the dedup drain before the compacted diff is
	// ready. Only affects the memfd-dedup path; off restores the prior
	// wait-for-dedup behavior.
	MemfdDedupInflightServeFlag = NewBoolFlag("memfd-dedup-inflight-serve", false)

	// MemfdDedupFreeIndexFlag frees the memfd dedup cache's packed index when
	// its memfd is released. The index only translates in-flight drain reads
	// to memfd offsets, which cannot be served once the memfd is gone, yet it
	// otherwise stays on the cache for as long as the diff store keeps it.
	// Only MemfdDedupInflightServeFlag pauses build an index, so elsewhere
	// this flag has nothing to free.
	MemfdDedupFreeIndexFlag = NewBoolFlag("memfd-dedup-free-index", false)

	// SnapshotCacheDropProvisionalHeaderFlag drops the two long-lived holders
	// of a pause's provisional memfile header: the local template's header
	// holder, cleared once Fetch has read it to build the memfile device, and the
	// snapshot the upload keeps, cleared as the upload is created. The device
	// keeps its own reference until the deduped or the published header
	// replaces it. Only MemfdDedupInflightServeFlag pauses build a provisional
	// header.
	SnapshotCacheDropProvisionalHeaderFlag = NewBoolFlag("snapshot-cache-drop-provisional-header", false)

	// PeerToPeerChunkTransferFlag enables peer-to-peer chunk routing.
	PeerToPeerChunkTransferFlag = NewBoolFlag("peer-to-peer-chunk-transfer", false)
	// PeerToPeerAsyncCheckpointFlag makes Checkpoint upload fire-and-forget instead
	// of synchronous. Only safe to enable after PeerToPeerChunkTransferFlag is ON.
	PeerToPeerAsyncCheckpointFlag = NewBoolFlag("peer-to-peer-async-checkpoint", false)

	// DeferRootfsExportFlag moves the rootfs diff seal (the reflink, which forces a
	// synchronous host->NVMe writeback) off the pause critical path. On the
	// suspend (pause) path, pause() ejects the cache and stops the sandbox, then
	// reflinks the diff in the background — nothing reads the diff until a later
	// resume. On the in-place checkpoint path, pause() swaps a fresh writable
	// cache in, resumes the VM, seals the frozen old cache in the background and
	// folds it back into the writable cache when done. Off by default; falls
	// back to the synchronous export when off or on a non-NBD provider.
	DeferRootfsExportFlag = NewBoolFlag("defer-rootfs-export", false)

	PersistentVolumesFlag           = NewBoolFlag("can-use-persistent-volumes", env.IsDevelopment())
	SandboxLabelBasedSchedulingFlag = NewBoolFlag("sandbox-label-based-scheduling", false)
	FreePageReportingFlag           = NewBoolFlag("free-page-reporting", false)
	FreezeUserCgroupFlag            = NewBoolFlag("freeze-user-cgroup", env.IsDevelopment())
	// FreezeGuestHierarchyFlag selects the hierarchy walk over the static user/pty list,
	// i.e. whether cgroups the customer created anywhere in the tree are frozen before a
	// pause. Default off: it changes which cgroups are stopped, which is a behaviour
	// change on the pause path.
	//
	// Evaluated here rather than in envd because envd has no LaunchDarkly, so the mode
	// travels on the /freeze call. That also means it can be ON at pause and OFF at the
	// following resume, which is why the thaw discovers what is frozen instead of
	// recomputing what should have been.
	FreezeGuestHierarchyFlag = NewBoolFlag("freeze-guest-hierarchy", false)

	// FreezeGuestHierarchyMaxCgroupsFlag bounds one hierarchy sweep. A safety guard, not
	// a performance one -- the walk is breadth-bounded along a 2-deep chain, so a normal
	// guest visits tens. It exists for a pathological or hostile hierarchy, the guest
	// being the threat model, and truncation is reported rather than swallowed.
	//
	// Safe to lower; the THAW's bound (in envd) is separate and must never be lowered,
	// because a thaw that truncates below what a freeze covered strands a guest frozen.
	FreezeGuestHierarchyMaxCgroupsFlag = NewIntFlag("freeze-guest-hierarchy-max-cgroups", 512)

	// CollapseEnvdHeapFlag makes the orchestrator ask envd to collapse its own
	// anonymous heap into 2 MiB hugepages just before pause, reducing the number
	// of distinct frames envd faults on resume. Off by default; rolled out via LD.
	CollapseEnvdHeapFlag = NewBoolFlag("collapse-envd-heap", false)

	// CollapseEnvdHeapTimeoutMsFlag bounds the pre-pause POST /collapse call, in
	// milliseconds. Collapsing migrates envd's scattered heap pages into
	// hugepages, which is heavier than the freeze sysfs write, so it gets a
	// larger, independent budget. Collapse is best-effort: a cut-short run still
	// helps, so this can be tuned per rollout without redeploying. The fallback
	// (returned when LD is unavailable or the flag is unset) is the default.
	CollapseEnvdHeapTimeoutMsFlag = NewIntFlag("collapse-envd-heap-timeout-ms", 10000) // 10s in milliseconds

	// FreezeUserCgroupTimeoutMsFlag bounds the pre-pause freeze call that
	// FreezeUserCgroupFlag enables, in milliseconds. The call waits for the workload's
	// cgroups to actually stop, and quiesce latency is the guest's cost, not ours: a
	// cgroup whose tasks are idle confirms in single-digit milliseconds, one in
	// continuous I/O has been measured taking seconds. The default keeps the historical
	// budget; raise it once the freeze metrics show how often it is the binding
	// constraint. envd is told to confirm within a margin of this, so one knob moves
	// both halves.
	//
	// The value bounds pause latency directly: a sandbox that will not quiesce holds the
	// pause for this long before we give up on it. That is the cost being traded against
	// snapshotting a running workload, and it is why raising it wants evidence.
	//
	// Effective ceiling of 10s. The shared sandbox HTTP client caps every request at that,
	// so a larger value here is silently truncated to it while the failure is still
	// recorded against the value set here. Tracked separately; until it is lifted, a value
	// above 10s buys nothing and makes the timeout metric misleading.
	FreezeUserCgroupTimeoutMsFlag = NewIntFlag("freeze-user-cgroup-timeout-ms", 2000) // 2s in milliseconds

	// VolumeFallbackToUnmatchedNodesFlag allows volume operations to fall back to
	// orchestrator nodes that don't advertise the volume's type label when every
	// labeled node fails with a retryable error. This is a transitional flag for
	// the volume-label migration: once every node is labeled, unlabeled nodes will
	// fail 100% of the time, so this should be turned off and removed afterwards.
	VolumeFallbackToUnmatchedNodesFlag = NewBoolFlag("volume-fallback-to-unmatched-nodes", true)

	// SandboxVolumeLabelBasedSchedulingFlag enables filtering orchestrator nodes
	// based on the volume types required by the sandbox. When enabled, labels
	// like "persistent-volume-type=nfs" are added to the required node labels
	// for sandbox placement.
	SandboxVolumeLabelBasedSchedulingFlag = NewBoolFlag("sandbox-volume-label-based-scheduling", false)

	// SandboxListMaxLagMsFlag is how far, in milliseconds, a team's sandbox list
	// may lag the store. With it set, each API replica shares one store read
	// between the team's concurrent list requests and keeps it that long, so at
	// 2000 a team is read at most every 2 s per replica however often it lists,
	// while reads succeed; a failed read is not kept. Target it at a team to
	// bound that team alone. The fallback, zero, keeps every request on its own
	// read, with the same store commands as before.
	SandboxListMaxLagMsFlag = NewIntFlag("sandbox-list-max-lag-ms", 0)

	// SandboxStorePerSandboxKeysFlag selects the key form new sandbox records
	// are written with: on, keys tagged with the sandbox ID, so one sandbox's
	// keys share a cluster slot; off, today's team-tagged keys. A record keeps
	// the form it was written with. Target it per environment through the
	// deployment_environment context. Read through BoolFlagOverride: a
	// replica starts on the team-tagged keys and keeps the form it last
	// selected while the flag is not served, by a client not ready, a value
	// of another type, a key the environment does not define, or a flag
	// turned off with no off variation. The flag must carry an off variation
	// of false, the UI's default, for a flip off to put every replica back
	// on the team-tagged keys.
	SandboxStorePerSandboxKeysFlag = NewBoolFlag("sandbox-store-per-sandbox-keys", false)

	// UnpaginatedTemplateListCapFlag caps GET /templates at 5000 templates; a
	// team above it gets a 400 pointing at GET /v2/templates. Evaluated per team.
	UnpaginatedTemplateListCapFlag = NewBoolFlag("unpaginated-template-list-cap", true)

	// UnpaginatedSandboxListCapFlag caps GET /sandboxes at 5000 running
	// sandboxes; a team above it gets a 400 pointing at GET /v2/sandboxes.
	// Evaluated per team.
	UnpaginatedSandboxListCapFlag = NewBoolFlag("unpaginated-sandbox-list-cap", true)

	NetworkTransformRulesFlag = NewBoolFlag("network-transform-rules", env.IsDevelopment())
	MaxNetworkRuleDomains     = NewIntFlag("max-network-rule-domains", 10)
	// MaxNetworkRuleHeaderValueLen caps the length of a header value in a
	// network transform rule, before placeholders are resolved. Evaluated per team.
	MaxNetworkRuleHeaderValueLen = NewIntFlag("max-network-rule-header-value-len", 2048)

	BYOPProxyEnabledFlag = NewBoolFlag("byop-proxy-enabled", true)

	// SandboxFirewallNonDNSUDPFlag selects what the slot firewall does with
	// guest UDP to ports other than 53: "off" leaves it alone, "count" counts
	// it, "drop" counts and drops it. Read at every chain build.
	SandboxFirewallNonDNSUDPFlag = NewStringFlag("sandbox-firewall-non-dns-udp", "off")

	// EgressProxyInterceptTracingFlag turns on connection, request and upstream
	// spans for a sandbox's TLS-intercepted egress. Target the sandbox or team
	// context; the fallback keeps interception at its existing transform span.
	EgressProxyInterceptTracingFlag = NewBoolFlag("egress-proxy-intercept-tracing", false)

	// SandboxIamTokensFlag gates the sandbox IAM workload token configuration
	// (iam.tokens) per team during beta.
	SandboxIamTokensFlag = NewBoolFlag("enable-sandbox-iam-tokens", env.IsDevelopment())

	// ResizableTemplatesFlag lets a team pass maxCpuCount on a template build.
	// Off, a request carrying the field is refused.
	ResizableTemplatesFlag = NewBoolFlag("resizable-templates", env.IsDevelopment())

	// ResizableTemplateDefaultMaxCpuFlag is the max CPU count applied to a
	// team's builds that omit maxCpuCount while ResizableTemplatesFlag is on;
	// 0 applies no default.
	ResizableTemplateDefaultMaxCpuFlag = NewIntFlag("resizable-template-default-max-cpu", 0)

	// CustomerSecretsFlag gates the customer-facing secret management routes
	// per project during rollout. It falls back to off, so a deployment that
	// cannot reach LaunchDarkly keeps the routes dark.
	CustomerSecretsFlag = NewBoolFlag("customer-secrets", false)

	DisableLegacyTeamMutationsFlag = NewBoolFlag("disable-legacy-team-mutations", false)

	// V4HeaderForUncompressedFlag forces the V4 header layout on uncompressed
	// uploads. Independent of compress-config: it changes the header format,
	// not whether data is compressed.
	V4HeaderForUncompressedFlag = NewBoolFlag("v4-header-for-uncompressed", false)

	// HeaderV5WriteFlag makes Pause emit V5 headers. When enabled it also
	// supersedes V4HeaderForUncompressedFlag for uncompressed uploads.
	HeaderV5WriteFlag = NewBoolFlag("header-v5-write", false)

	// CompressRightSizedFramesFlag is a kill switch for the exact-length
	// compressed frame outputs. Off restores outputs that keep the encoder's
	// frame-sized buffer until the frame is uploaded and cached. The
	// compressed bytes are the same either way. Evaluated per upload with the
	// compress-config file type and use case.
	CompressRightSizedFramesFlag = NewBoolFlag("compress-right-sized-frames", true)

	// CompressSharedCompressorsFlag is a kill switch for sharing compressor
	// pools across uploads. Off makes every upload build its own encoders and
	// drop them when it finishes. The compressed bytes are the same either
	// way. Evaluated per upload with the compress-config file type and use
	// case.
	CompressSharedCompressorsFlag = NewBoolFlag("compress-shared-compressors", true)

	// SnapshotCacheAncestorStorageFallbackFlag lets a snapshot upload resolve an
	// ancestor whose upload future fired successfully but whose template-cache
	// entry is gone, instead of failing the upload. An entry the child already
	// carries is kept; otherwise it is healed from the ancestor's stored header
	// without LoadHeader's backfill, so the child gets the ancestor's entry only
	// as that header carries it, or the empty entry a header older than the
	// Builds map always gets. Evaluated at each wait that reaches that case.
	// It changes bytes written into headers that reach storage, and turning it
	// off does not rewrite headers written while it was on.
	SnapshotCacheAncestorStorageFallbackFlag = NewBoolFlag("snapshot-cache-ancestor-storage-fallback", false)

	// SnapshotCacheReleaseSupersededFlag lets the template cache delete a pause
	// layer as soon as a later pause on the node has superseded it, nothing
	// holds a pin on it and its devices have resolved, instead of keeping it
	// to its TTL. It acts only together with
	// SnapshotCacheAncestorStorageFallbackFlag: a released ancestor's upload
	// future outlives its entry, and without the fallback a descendant's upload
	// fails on it. Supersession and pins are recorded whatever the flag says;
	// it is read wherever the release would act, so a flip takes effect at each
	// entry's next pin return, supersession or fetch completion. Turning it off
	// stops further releases and restores nothing already released.
	SnapshotCacheReleaseSupersededFlag = NewBoolFlag("snapshot-cache-release-superseded", false)

	// ResumeOriginNodeRemapFlag enables repointing a snapshot's origin_node_id to
	// the fallback node a resume timed out on. The node's local cache is warming
	// from the in-progress snapshot pull, so pinning the retry to it avoids
	// re-pulling the snapshot onto yet another node.
	ResumeOriginNodeRemapFlag = NewBoolFlag("resume-origin-node-remap", false)

	// BuildEnsureFreeDiskSpace grows the rootfs after build steps and before finalize.
	BuildEnsureFreeDiskSpace = NewBoolFlag("build-ensure-free-disk-space", false)
)
View Source
var (
	// EgressRetirementTimeoutMsFlag sets the wait for retiring egress connections
	// at network release. Callers accept positive milliseconds that fit in a
	// time.Duration, otherwise using the one-minute fallback. Updates affect
	// future retirements.
	EgressRetirementTimeoutMsFlag = NewIntFlag("egress-retirement-timeout-ms", 60000)

	// RemoteClusterInstancesPerConnectionFlag caps how many of a remote
	// cluster's instances the api places on one shared gRPC connection to the
	// cluster's edge; the pool opens another connection once every connection
	// is full. An AWS ALB serves at most 128 concurrent streams per HTTP/2
	// connection and a sync round calls every instance at once, so the
	// fallback keeps half of each connection's streams for sandbox calls.
	// Evaluated against the cluster's context as each instance joins; values
	// below one count as one.
	RemoteClusterInstancesPerConnectionFlag = NewIntFlag("remote-cluster-instances-per-connection", 64)

	// RemoteClusterMinConnectionsFlag is the fewest shared gRPC connections the
	// api keeps to a remote cluster's edge, however few instances it has.
	// Evaluated against the cluster's context as each instance joins; values
	// below one count as one.
	RemoteClusterMinConnectionsFlag = NewIntFlag("remote-cluster-min-connections", 4)

	MaxSandboxesPerNode      = NewIntFlag("max-sandboxes-per-node", 200)
	APIIdempotencyRoutes     = NewJSONFlag("api-idempotency-routes", ldvalue.Null())
	APIIdempotencyTTLSeconds = NewIntFlag("api-idempotency-ttl-seconds", 86400)
	// The LD keys keep the legacy "gcloud-" prefix, but the limits apply to uploads on all storage providers.
	StorageConcurrentUploadLimit  = NewIntFlag("gcloud-concurrent-upload-limit", 8)
	StorageMaxUploadTasks         = NewIntFlag("gcloud-max-tasks", 16)
	ClickhouseBatcherMaxBatchSize = NewIntFlag("clickhouse-batcher-max-batch-size", 1000)
	ClickhouseBatcherMaxDelay     = NewIntFlag("clickhouse-batcher-max-delay", 1000) // 1s in milliseconds
	ClickhouseBatcherQueueSize    = NewIntFlag("clickhouse-batcher-queue-size", 1000)
	BestOfKSampleSize             = NewIntFlag("best-of-k-sample-size", 3)                           // Default K=3
	BestOfKMaxOvercommit          = NewIntFlag("best-of-k-max-overcommit", 400)                      // Default R=4 (stored as percentage, max over-commit ratio)
	BestOfKAlpha                  = NewIntFlag("best-of-k-alpha", 50)                                // Default Alpha=0.5 (stored as percentage for int flag, current usage weight)
	PlacementHugepageLimitPercent = NewIntFlag("placement-hugepage-limit-percent", 0)                // Share of a node's hugepage pool ceiling placement may commit (of its memory outside the pool, for a sandbox without hugepages); 0 disables the check
	PlacementMemoryMaxOvercommit  = NewIntFlag("placement-memory-max-overcommit", 0)                 // Template RAM of a node's sandboxes as a percentage of its base hugepage pool (its total memory, for a sandbox without hugepages), past which placement refuses; 0 disables the check
	EnvdInitTimeoutMilliseconds   = NewIntFlag("envd-init-request-timeout-milliseconds", 50)         // Timeout for envd init request in milliseconds
	EnvdTimeoutMilliseconds       = NewIntFlag("envd-timeout-milliseconds", envdTimeoutFallbackMs()) // Timeout for waiting for envd on resume; falls back to ENVD_TIMEOUT env var (default 10s)
	// EnvdInitConnectTimeoutMilliseconds bounds each connect of the held envd init
	// request. Read with EnvdInitHeldRequestFlag; a value below 1000 is raised to it, and
	// a value at or below zero reads as the fallback.
	EnvdInitConnectTimeoutMilliseconds = NewIntFlag("envd-init-connect-timeout-milliseconds", 5000)
	// GuestSyncTimeoutMs overrides the mandatory pre-pause guest-sync deadline
	// for filesystem-only snapshots, in milliseconds. 0 (default) derives the
	// timeout from guest RAM; a positive value pins it.
	GuestSyncTimeoutMs = NewIntFlag("guest-sync-timeout-milliseconds", 0)
	// PauseAdmissionGraceMs gates the pause/checkpoint snapshot-admission
	// pre-flight, in milliseconds. Negative (default) disables the pre-flight;
	// 0 probes the parent header's readiness without waiting; a positive value
	// waits up to that long before refusing retryably.
	PauseAdmissionGraceMs = NewIntFlag("pause-admission-grace-milliseconds", -1)
	// PauseEnvdHealthTimeoutMs gates the envd health probe every snapshot runs
	// before anything destructive, in milliseconds. 0 or less (default -1)
	// disables the probe: an HTTP request cannot complete inside a zero
	// deadline, so unlike PauseAdmissionGraceMs zero is not an instant probe.
	// A positive value probes envd's /health with that timeout, capped at the
	// sandbox HTTP client's 10s limit. When envd does not answer, a memory
	// pause proceeds and the snapshot is recorded as taken over an
	// unresponsive agent, unless the caller requires a healthy guest, in
	// which case it is refused retryably with an ENVD_UNRESPONSIVE detail;
	// filesystem-only captures and checkpoints (forks, snapshot templates)
	// are always refused that way, since a filesystem-only capture needs the
	// agent to freeze the rootfs and a fork of a hung agent is born dead. A
	// rollout brake: once production confirms the refusal rate matches the
	// dead-guest rate, the timeout becomes a constant and the flag is
	// retired.
	PauseEnvdHealthTimeoutMs = NewIntFlag("pause-envd-health-timeout-milliseconds", -1)
	// PauseAdmissionDiskHeadroomMiB makes a node refuse a pause, retryably and
	// before anything destructive, when the filesystem holding its build
	// directory cannot take the snapshot's capture (guest memory plus the
	// rootfs cache plus a snapfile allowance, twice that when template storage
	// is a directory on the same filesystem, counting captures already admitted
	// and not yet on disk) and still keep this many MiB free. Negative, the
	// default, turns the check off; the fallback reads
	// PAUSE_ADMISSION_DISK_HEADROOM_MIB so a deployment without LaunchDarkly can
	// turn it on, as E2B Embed does.
	PauseAdmissionDiskHeadroomMiB = NewIntFlag("pause-admission-disk-headroom-mib", envIntOr("PAUSE_ADMISSION_DISK_HEADROOM_MIB", -1))
	// OrchestratorGOGCPercentFlag sets the orchestrator's Go GC percent. 10 to
	// 100 is written with debug.SetGCPercent. -1 (default) and any other
	// value, 0 included, keep the percent read when the controller was built:
	// nothing is written unless an applied value has to be undone.
	OrchestratorGOGCPercentFlag = NewIntFlag("orchestrator-gogc-percent", -1)
	// PauseRefusalRestoreFlag gates the API-side restore of a retryably
	// refused pause: record kept, routing re-registered, state back to
	// Running. Off (default), a busy-node refusal still ends today's way — the
	// record is removed, the live sandbox is reaped as an orphan shortly
	// after, and the pause endpoint answers today's generic error rather than
	// a 503 whose retry could not succeed. A refusal the node types as a
	// checkpoint in flight restores whatever the flag says: the node has
	// proven the sandbox alive and the refusal ends with the checkpoint. The fallback reads
	// PAUSE_REFUSAL_RESTORE so a deployment without LaunchDarkly can turn it on.
	PauseRefusalRestoreFlag = NewBoolFlag("pause-refusal-restore", envBoolOr("PAUSE_REFUSAL_RESTORE", false))
	// CreateMemoryRefusalFlag changes what a create answers when the hugepage
	// pool cannot back its guest memory. On, while a sandbox on the node is
	// still tearing down, the create is refused with ResourceExhausted, so
	// placement retries the node once the pages are back; with nothing tearing
	// down it fails at once and says why. Off (default), such a create fails
	// as an internal error and placement excludes the node, which on a
	// one-node deployment turns a create sent right after a kill into a
	// failure. The fallback reads CREATE_MEMORY_REFUSAL so a deployment
	// without LaunchDarkly can turn it on.
	CreateMemoryRefusalFlag = NewBoolFlag("create-memory-refusal", envBoolOr("CREATE_MEMORY_REFUSAL", false))
	// CreateHugePageAdmissionFlag refuses a hugepage create or resume before
	// it starts when the node cannot allocate the guest's memory in hugepages,
	// less what the starts already admitted may still take. Off (default), the
	// start goes ahead, and a guest that cannot fault in its pages fails its
	// start or crashes a neighbour mid-run. The fallback reads
	// CREATE_HUGEPAGE_ADMISSION so a deployment without LaunchDarkly can turn
	// it on.
	CreateHugePageAdmissionFlag   = NewBoolFlag("create-hugepage-admission", envBoolOr("CREATE_HUGEPAGE_ADMISSION", false))
	MaxCacheWriterConcurrencyFlag = NewIntFlag("max-cache-writer-concurrency", 10)

	// BuildCacheMaxUsagePercentage the maximum percentage of the cache disk storage
	// that can be used before the cache starts evicting items.
	BuildCacheMaxUsagePercentage = NewIntFlag("build-cache-max-usage-percentage", 85)
	BuildProvisionVersion        = NewIntFlag("build-provision-version", 0)

	// BuildEnvdMemoryProtection, when enabled at build time, renders a fixed
	// memory.min/memory.low request for envd, the same on every template, and
	// installs a system.slice drop-in requesting the same, so the kernel grants
	// envd's protection instead of prorating it to nothing. Evaluated once per
	// build with the template and team contexts. When on, the request it
	// renders enters the base-layer cache key of every build that renders the
	// rootfs files, so such a build never reuses a layer built off, and off
	// keeps the key those layers are already stored under wherever
	// BuildProvisionVersion is set explicitly (a build from another template
	// inherits its parent's layer and files, whatever its own flag). Where that
	// flag is at its fallback the provision version is a hash of the baked
	// files, which the drop-in template changes once, so those deployments
	// rebuild their base layers on landing whatever this flag says.
	// Disabled by default: the unit keeps the request it carries today.
	BuildEnvdMemoryProtection = NewBoolFlag("build-envd-memory-protection", false)

	// NBDConnectionsPerDevice the number of NBD socket connections per device
	NBDConnectionsPerDevice = NewIntFlag("nbd-connections-per-device", 1)

	// NBDAsyncWriteZeroesFlag, when enabled, handles NBD WRITE_ZEROES/TRIM
	// commands in a goroutine instead of inline on the dispatch read loop.
	// Inline handling can stall the read loop via head-of-line blocking on the
	// shared write lock (when a reply writer is blocked on a full socket send
	// buffer), which makes the kernel time out the NBD connection and surfaces
	// as guest I/O errors. Disabled by default.
	NBDAsyncWriteZeroesFlag = NewBoolFlag("nbd-async-write-zeroes", false)

	// MemoryPrefetchMaxFetchWorkers is the maximum number of parallel fetch workers per sandbox for memory prefetching.
	// Fetching is I/O bound so we can have more parallelism.
	MemoryPrefetchMaxFetchWorkers = NewIntFlag("memory-prefetch-max-fetch-workers", 16)

	// MemoryPrefetchMaxCopyWorkers is the maximum number of parallel copy workers per sandbox for memory prefetching.
	// Copy uses uffd syscalls, so we limit parallelism to avoid overwhelming the system.
	MemoryPrefetchMaxCopyWorkers = NewIntFlag("memory-prefetch-max-copy-workers", 8)

	// MemoryPrefetchCoalesceMaxMB caps how many contiguous prefetch blocks are
	// merged into a single source.Slice fetch (in MiB of extent size). 0
	// disables coalescing: every block is fetched individually, matching
	// today's behavior. The copy phase is unaffected either way — it always
	// installs one page at a time, because Userfaultfd.Prefault installs a
	// single page per call.
	MemoryPrefetchCoalesceMaxMB = NewIntFlag("memory-prefetch-coalesce-max-mb", 0)

	// ResumePrefetchSourceFlag selects which trace the resume prefetcher
	// replays:
	//   "init"     — only the build-time / harvested read-hot init trace
	//                (meta.Prefetch.Memory), prefaulted. Preserves today's
	//                behavior, so this is the default and a no-op-equivalent.
	//   "last-cycle" — only the sandbox's own pause diff (the pages the last
	//                resume→pause cycle wrote), derived from the memfile header
	//                and replayed fetch-only.
	//   "both"     — init first (prefaulted), then last-cycle (fetch-only) behind
	//                a barrier, so the large last-cycle fetch stays off the
	//                resume-critical path.
	//   "off"      — kill switch, no resume prefetch.
	// Unknown values fall back to "init".
	ResumePrefetchSourceFlag = NewStringFlag("resume-prefetch-source", "init")

	// ResumeLastCyclePrefetchMaxMiBFlag caps how much of the last-cycle diff a single
	// resume prefetches, in MiB. -1 (the default, negative = no limit per the
	// codebase convention) is uncapped; the recorded diff is small by
	// construction, so this exists to throttle the heavy-churn tail against the
	// shared object-store pool without a redeploy. A non-negative N keeps the
	// first N MiB of blocks in offset order and leaves the rest to demand-fault.
	ResumeLastCyclePrefetchMaxMiBFlag = NewIntFlag("resume-last-cycle-prefetch-max-mib", -1)

	// PauseResumePrefetchHarvestFlag makes the orchestrator, after a pause
	// snapshot or an in-place checkpoint is durable, run a throwaway warm resume
	// of the just-written artifact (driven by envd /init, workload frozen, egress
	// denied) to record the resume page-fault trace and turn it into a prefetch
	// mapping. The in-place checkpoint has no resume of its own to trace, so
	// this is the only way a template it produces gets an init mapping. The
	// code fallback is off, but the flag already serves true in every
	// production environment, so wherever in-place-checkpoint is on the
	// checkpoint harvest runs too: this flag gates both producers at once and
	// turning it off also stops the pause harvest. To stop only the checkpoint
	// harvest, turn in-place-checkpoint off (read per checkpoint; a resume-fresh
	// checkpoint records its own mapping and runs no throwaway). The harvest is
	// best-effort and never affects the pause or checkpoint result.
	PauseResumePrefetchHarvestFlag = NewBoolFlag("pause-resume-prefetch-harvest", false)

	// PauseResumePrefetchConsumeFlag controls whether a harvested mapping is
	// persisted into the pause artifact metadata (and therefore replayed on the
	// customer's next resume). When off, the harvest still runs and emits its
	// trace-size metrics but does NOT write the mapping, so resumes are
	// unaffected — letting us validate harvest behaviour with no customer-visible
	// change before enabling prefetch on resume. Off by default.
	PauseResumePrefetchConsumeFlag = NewBoolFlag("pause-resume-prefetch-consume", false)

	// PauseResumePrefetchHarvestTimeoutMsFlag bounds the throwaway harvest resume
	// (slot-hold cap), in milliseconds. The harvest is best-effort: a cut-short
	// run is discarded (the build is simply re-harvested on its next pause), so
	// erring short is cheap. A normal warm harvest completes in a few seconds; the
	// default leaves headroom for a large warm resume to fully drain while keeping
	// the worst-case slot hold modest. Tunable per rollout via LD; the fallback
	// (returned when LD is unavailable or the flag is unset) is the default.
	PauseResumePrefetchHarvestTimeoutMsFlag = NewIntFlag("pause-resume-prefetch-harvest-timeout-ms", 15000) // 15s

	// TCPFirewallMaxConnectionsPerSandbox is the maximum number of concurrent TCP firewall
	// connections allowed per sandbox. Negative means no limit.
	TCPFirewallMaxConnectionsPerSandbox = NewIntFlag("tcpfirewall-max-connections-per-sandbox", -1)

	// SandboxMaxIncomingConnections is the maximum number of concurrent HTTP proxy
	// connections allowed per sandbox. Negative means no limit.
	SandboxMaxIncomingConnections = NewIntFlag("sandbox-max-incoming-connections", -1)

	// BuildBaseRootfsSizeLimitMB is the maximum size of the base rootfs filesystem created from the OCI image, in MB.
	BuildBaseRootfsSizeLimitMB = NewIntFlag("build-base-rootfs-size-limit-mb", 25000)

	// ClientProxyResumeParkingBudgetMs gates the retries of one resume
	// flight, counted from its first retryable failure and read when the
	// flight is created: no retry starts past it, an attempt under way keeps
	// its ceiling while a caller waits, and is cut at the budget's end once
	// every caller has left.
	ClientProxyResumeParkingBudgetMs = NewIntFlag("client-proxy-resume-parking-budget-ms", 15000)

	// ClientProxyResumeParkingLotSize caps the requests one client-proxy
	// process keeps waiting on retried resumes, read by each request at its
	// park transition; the rest are shed with a 503.
	ClientProxyResumeParkingLotSize = NewIntFlag("client-proxy-resume-parking-lot-size", 512)

	// MinAutoResumeTimeoutSeconds is the minimum auto-resume timeout in seconds.
	// This prevents thrashing from very short timeouts.
	MinAutoResumeTimeoutSeconds = NewIntFlag("minimum-autoresume-timeout", 300)

	// BuildReservedDiskSpaceMB is the amount of disk space in MB reserved for root on the guest filesystem.
	// Reserved blocks are only usable by root (uid 0), protecting the guest OS from disk-full conditions.
	BuildReservedDiskSpaceMB = NewIntFlag("build-reserved-disk-space-mb", 256)

	// BuildBootDiagnosticsFlag inspects the rootfs before each build cold boot and annotates
	// an envd timeout with what it found. Off means no inspection.
	BuildBootDiagnosticsFlag = NewBoolFlag("build-boot-diagnostics", false)

	// MaxStartingInstancesPerNode limits concurrent sandbox start/resume operations on a single orchestrator node.
	// Must be > 0.
	MaxStartingInstancesPerNode = NewIntFlag("max-starting-instances-per-node", 3)

	// MaxConcurrentEvictions caps the number of sandbox evictions that can run
	// in parallel per API instance. Excess items remain expired in the store
	// and are picked up by the next eviction tick. Must be > 0; non-positive
	// values are ignored at refresh time.
	MaxConcurrentEvictions = NewIntFlag("max-concurrent-evictions", 256)

	// AutoPauseOverstayBudgetMs is how long the evictor keeps retrying a memory
	// snapshot for an expired auto-pause sandbox the node refuses, counted from
	// the first refusal of the current episode, before it requests a
	// filesystem-only snapshot instead (no memory parent, so it cannot be
	// refused for one). Same sign convention as PauseAdmissionGraceMs:
	// negative = never degrade (retry for as long as the node refuses), 0 = no
	// retries (degrade at the first refusal), positive = the budget. Only ever
	// consulted on a busy-node refusal, which reaches the evictor only with
	// PauseRefusalRestoreFlag on; a checkpoint-in-flight refusal reaches it
	// regardless but never degrades and does not charge this budget.
	AutoPauseOverstayBudgetMs = NewIntFlag("auto-pause-overstay-budget-milliseconds", 120000)

	// AutoPauseEnvdGraceMs is how long the evictor honours the guest agent's
	// refusal of an expired auto-pause, from the first envd refusal of its
	// current episode, before retrying the memory pause once without the
	// probe. Sign convention as AutoPauseOverstayBudgetMs: negative never,
	// 0 at the first refusal, positive the grace. Inert until
	// PauseEnvdHealthTimeoutMs is on. A rollout brake like that flag: once
	// production shows how long a guest takes to recover, the grace becomes
	// a constant and the flag is retired with it.
	AutoPauseEnvdGraceMs = NewIntFlag("auto-pause-envd-grace-milliseconds", 120000)

	// MaxConcurrentSnapshotUpserts limits concurrent UpsertSnapshot calls (pause + snapshot template paths).
	// 0 or negative disables throttling (unlimited concurrency).
	MaxConcurrentSnapshotUpserts = NewIntFlag("max-concurrent-snapshot-upserts", 0)
	// MaxConcurrentSandboxListQueries limits concurrent GetSnapshotsWithCursor calls in the sandbox list path.
	// 0 or negative disables throttling (unlimited concurrency).
	MaxConcurrentSandboxListQueries = NewIntFlag("max-concurrent-sandbox-list-queries", 0)

	// PausedSandboxListBatchLimit caps the number of rows requested per GetSnapshotsWithCursor
	// query when excluding running sandboxes in GET /v2/sandboxes.
	// 0 or negative disables batching (fetches queryLimit + len(runningSandboxesIDs) in one query).
	// Evaluated per team.
	PausedSandboxListBatchLimit = NewIntFlag("paused-sandbox-list-batch-limit", 0)

	// DBMaxConnLifetimeSeconds overrides pgxpool MaxConnLifetime when positive.
	// 0 or negative keeps pgxpool's default (1h, or the value in the DSN).
	DBMaxConnLifetimeSeconds = NewIntFlag("db-max-conn-lifetime-seconds", 0)
	// DBMaxConnLifetimeJitterSeconds overrides pgxpool MaxConnLifetimeJitter when positive.
	// 0 or negative keeps pgxpool's default (0, or the value in the DSN).
	DBMaxConnLifetimeJitterSeconds = NewIntFlag("db-max-conn-lifetime-jitter-seconds", 0)

	// MaxConcurrentSnapshotBuildQueries limits concurrent GetSnapshotBuilds calls (e.g. sandbox delete).
	// 0 or negative disables throttling (unlimited concurrency).
	MaxConcurrentSnapshotBuildQueries = NewIntFlag("max-concurrent-snapshot-build-queries", 0)

	MinChunkerReadSizeKB = NewIntFlag("min-chunker-read-size-kb", 16)

	// MaxParallelBuildReadSegments limits concurrent backing reads within one fragmented build read.
	// 1 or lower keeps the existing serial path.
	MaxParallelBuildReadSegments = NewIntFlag("max-parallel-build-read-segments", 1)
)
View Source
var (
	BuildFirecrackerVersion = NewStringFlag("build-firecracker-version", env.GetEnv("DEFAULT_FIRECRACKER_VERSION", DefaultFirecrackerVersion))
	BuildKernelVersion      = NewStringFlag("build-kernel-version", env.GetEnv("DEFAULT_KERNEL_VERSION", DefaultKernelVersion))
	// BuildEnvdVersion selects which staged envd binary a template build bakes
	// into the rootfs — the envd counterpart of BuildKernelVersion /
	// BuildFirecrackerVersion, same default mechanism. "promoted" (the
	// fallback) is the node-local promoted binary; a concrete version id
	// (e.g. v0.7.0, or a git SHA while those age out) selects a staged binary
	// (the flat envd.<id> sibling or the release bucket's <id>/envd layout,
	// see build/core/envd.ResolveBuildBinary). A pinned target that is not
	// staged FAILS the build rather than silently baking a different envd —
	// feature gates key on the baked version, so a silent substitute
	// misgates. The build-site LD context carries template/team, so cohort
	// canaries come for free.
	BuildEnvdVersion = NewStringFlag("build-envd-version", env.GetEnv("DEFAULT_ENVD_VERSION", DefaultEnvdVersion))
	BuildIoEngine    = NewStringFlag("build-io-engine", "Sync")

	// BuildKernelCmdlineArgs supplies extra guest kernel command line parameters at
	// template build time, keyed on team, as a command line fragment:
	//
	//	psi=1
	//	psi=1 nokaslr
	//
	// Empty (the default) is the default command line, so a team that is not targeted is
	// unaffected. Adding a parameter is a flag edit — no
	// orchestrator change and no deploy.
	//
	// Parsed the way the kernel parses a command line: whitespace separates parameters,
	// the first '=' separates a name from its value, and a parameter with no '=' has an
	// empty value. The orchestrator rejects the whole fragment if it sets a parameter it
	// reserves (init, clocksource, root, ip, console, rootflags, panic, reboot, loglevel,
	// quiet, selinux — see packages/orchestrator/pkg/sandbox/fc), falling back to the default
	// command line rather than failing the build. The parsed parameters are recorded in
	// the template's metadata and replayed when a filesystem-only snapshot cold-boots, so
	// a snapshot keeps booting the way it was built even if this flag later changes.
	BuildKernelCmdlineArgs = NewStringFlag("build-kernel-cmdline-args", "")

	// BuildCPUTemplate is the per-team custom Firecracker CPU template every layer of a build
	// boots with, as the PUT /cpu-config body.
	// A template the build's host or Firecracker version cannot apply falls back to none.
	// The applied template is stored in the template's metadata and replayed on cold boot.
	BuildCPUTemplate = NewJSONFlag("build-cpu-template", ldvalue.Null())

	// RebootCPUTemplateOverride replaces the build's CPU template on a filesystem-only cold
	// boot: {"template": <PUT /cpu-config body>}; {"template": {}} boots with none. {} or null
	// (the default) boots the build's template. The applied template is recorded as the
	// running one, so the next pause stores it, while the build's template is kept and
	// returns once the flag clears.
	// A value that does not parse is logged and ignored; one the resolved Firecracker version
	// or host cannot apply fails the boot, like a stored template would.
	RebootCPUTemplateOverride = NewJSONFlag("reboot-cpu-template-override", ldvalue.Null())

	// EnvdUpgradeTargetFlag drives the resume-time envd live-upgrade.
	// Multivariate string:
	//   "off"        (fallback) — no upgrade; dev has no LD so this is inert & safe.
	//   "promoted"   — track the node-local promoted envd (HOST_ENVD_PATH); upgrade
	//                  whenever it differs from the sandbox's built-with version
	//                  (no per-publish flag edits needed).
	//   "<version>"  — pin a specific staged binary, in either layout beside the
	//                  promoted one: the flat /fc-envd/envd.<version> sibling or
	//                  the release bucket's /fc-envd/<version>/envd directory.
	//                  Release names may carry dots and hyphens (v0.7.0,
	//                  v0.8.0-rc1); legacy git-SHA suffixes keep resolving while
	//                  the old envd.<sha> objects age out.
	// The resume-site LD context carries envd-version/team/template, so %-ramp
	// and cohort canaries come for free. The fallback is env-overridable
	// (ENVD_UPGRADE_TARGET) so it can be exercised where there is no LD (dev),
	// mirroring build-firecracker-version's DEFAULT_FIRECRACKER_VERSION.
	EnvdUpgradeTargetFlag = NewStringFlag("envd-upgrade-target", env.GetEnv("ENVD_UPGRADE_TARGET", "off"))
	// EnvdOfflineUpgradeTargetFlag drives the OFFLINE envd upgrade of a
	// filesystem-only snapshot: at cold-boot resume the rootfs binary is rewritten
	// (jailed debugfs) before the guest boots, reaching envd too old to self-upgrade
	// (< MinEnvdVersionForUpgrade). Same value grammar and resolver as
	// EnvdUpgradeTargetFlag ("off" / "promoted" / "<version>"); a SEPARATE flag so
	// the newer/riskier offline mechanism ramps independently of the live path. The
	// fallback is env-overridable (ENVD_OFFLINE_UPGRADE_TARGET) for dev, where there
	// is no LD. Default off.
	EnvdOfflineUpgradeTargetFlag = NewStringFlag("envd-offline-upgrade-target", env.GetEnv("ENVD_OFFLINE_UPGRADE_TARGET", "off"))

	// EnvdBinaryCacheFlag serves the envd upgrade paths from a node-local copy of
	// the host envd binary instead of re-reading it from the gcsfuse mount: the
	// version probe, the live delivery to a running envd, and the offline rootfs
	// swap's staging copy. Off keeps every one of those reading the source
	// directly, which is the behaviour before this flag existed.
	//
	// It gates a caching optimisation, not a new mechanism, so the risk it
	// isolates is the cache serving a stale binary — an upgrade delivering
	// something other than the version it recorded. That is recoverable (the
	// version arbiter refuses to record a success it cannot confirm) but worth a
	// kill switch that needs no deploy. Falls back on in development, where there
	// is no LD and the path would otherwise never be exercised.
	// The fallback is env-overridable (ENVD_BINARY_CACHE) so the cached and
	// uncached paths can be compared on a cluster with no LaunchDarkly, where the
	// alternative is two binary deploys.
	//
	// Ramp it on a NODE-SCOPED key only: deployment (the domain, so effectively the
	// cluster), instance-group, or orchestrator (the node, carrying its build as an
	// attribute). Those are what the orchestrator attaches to every evaluation, so
	// all three read sites agree on them. A sandbox- or team-keyed rule is absent
	// at the startup warm, which runs before any sandbox exists -- such a rule
	// still gates both upgrade paths but silently disables the pre-warm, so every
	// node's first eligible resume defers. A template-keyed rule matches the
	// offline path only, since the live path carries the template as an attribute
	// of the sandbox context rather than as a context of its own. None of that is a
	// limitation worth lifting: the subject of this flag is a cache shared by every
	// sandbox on the node, so the node, its group and its cluster are the cohorts
	// that mean anything.
	EnvdBinaryCacheFlag = NewBoolFlag("envd-binary-cache", envBoolOr("ENVD_BINARY_CACHE", env.IsDevelopment()))
	// FsOnlyResumeCPUModelFlag restricts where a cold boot (a resume of a
	// filesystem-only snapshot, a memory:false resume, or a sandbox created from a
	// memory:false snapshot template) may run: placement keeps only nodes
	// reporting this CPU model, on top of the build-compatibility rule every
	// sandbox is already subject to. The value is a bare CPU model as
	// /proc/cpuinfo reports it; see the machineinfo model constants.
	//
	// Empty (the default) turns the restriction off, leaving cold boots on the
	// cross-generation rule a memory restore uses. A deployment
	// with no LaunchDarkly therefore keeps placing them exactly as before, rather
	// than needing an LD rule to unpin itself. Memory restores never read it.
	FsOnlyResumeCPUModelFlag = NewStringFlag("fs-only-resume-cpu-model", "")

	// ExtraCompatibleNodeModelsFlag adds CPU model pairs to the hardcoded
	// compatibility rule, as a JSON object from build model to node models:
	// {"106": ["173"]} lets n2 builds run on C4 Granite Rapids nodes. Pairs are
	// one-way, and architecture and family must still match.
	//
	// Null (the default) or a malformed value adds nothing. It applies to every
	// placement, and FsOnlyResumeCPUModelFlag still narrows on top of it.
	ExtraCompatibleNodeModelsFlag = NewJSONFlag("extra-compatible-node-models", ldvalue.Null())

	DefaultPersistentVolumeType = NewStringFlag("default-persistent-volume-type", "")
	BuildNodeInfo               = NewJSONFlag("preferred-build-node", ldvalue.Null())
	FirecrackerVersions         = NewJSONFlag("firecracker-versions", ldvalue.FromJSONMarshal(firecrackerVersionsFallback))

	// ClickhouseReadEndpointFlag selects which ClickHouse DSN to use for reads.
	// "" (empty) → singular CLICKHOUSE_CONNECTION_STRING (self-managed default).
	// "0", "1", ... → index into CLICKHOUSE_CONNECTION_STRINGS
	ClickhouseReadEndpointFlag = NewStringFlag("clickhouse-read-endpoint", "")

	// ClickhouseWriteFanoutFlag: when false, drop writes to alternate
	// ClickHouse endpoints (CLICKHOUSE_CONNECTION_STRINGS). Default DSN
	// is unaffected.
	ClickhouseWriteFanoutFlag = NewBoolFlag("clickhouse-write-fanout", false)

	// ClickhouseHostStatsAsyncInsertFlag sets async_insert=1 on every
	// sandbox_host_stats flush. Each orchestrator flushes its own small batch,
	// so without it the server writes one tiny part per node per flush; with
	// it the server buffers those inserts and writes one part per buffer flush.
	// Used as the fallback when the shared async flag cannot be evaluated.
	ClickhouseHostStatsAsyncInsertFlag = NewBoolFlag("clickhouse-host-stats-async-insert", false)

	// ClickhouseAsyncInsertFlag shares the existing async key across named writers.
	// Do not seed the offline store: each writer supplies its own legacy fallback.
	ClickhouseAsyncInsertFlag        = BoolFlag{/* contains filtered or unexported fields */}
	ClickhouseWaitForAsyncInsertFlag = NewBoolFlag("clickhouse-wait-for-async-insert", true)
)

BuildIoEngine Sync is used by default as there seems to be a bad interaction between Async and a lot of io operations.

View Source
var BlockDriveThrottleConfig = NewJSONFlag("block-drive-throttle-config", ldvalue.FromJSONMarshal(map[string]any{
	"ops":       map[string]any{"bucketSize": -1, "oneTimeBurst": 0, "refillTimeMs": 1000},
	"bandwidth": map[string]any{"bucketSize": -1, "oneTimeBurst": 0, "refillTimeMs": 1000},
}))

BlockDriveThrottleConfig controls per-sandbox block device (disk) throttling via Firecracker's VMM-level token bucket rate limiters on the rootfs drive. Structure mirrors the Firecracker RateLimiter API: two independent token buckets. Set bucketSize to -1 to disable a bucket.

Ops bucket (IOPS): effective rate = ops.bucketSize * 1000 / ops.refillTimeMs ops/s. Bandwidth bucket (bytes): effective rate = bandwidth.bucketSize * 1000 / bandwidth.refillTimeMs bytes/s.

View Source
var CleanNFSCache = NewJSONFlag("clean-nfs-cache", ldvalue.Null())
View Source
var CompressConfigFlag = NewJSONFlag("compress-config", ldvalue.FromJSONMarshal(map[string]any{
	"compressBuilds":     false,
	"compressionType":    "",
	"compressionLevel":   0,
	"frameSizeKB":        0,
	"minPartSizeMB":      0,
	"frameEncodeWorkers": 0,
	"encoderConcurrency": 0,
}))

CompressConfigFlag controls compression during template builds. When compressBuilds is true, builds upload exclusively compressed data (no uncompressed fallback). When false, exclusively uncompressed with V3 headers (unless V4HeaderForUncompressedFlag is set).

View Source
var ErrEnvdSourceStalled = errors.New("envd source did not answer in time")

ErrEnvdSourceStalled is what an injected stat or version probe wraps when the source did not answer in time. The resolver maps it to ReasonSourceStalled.

View Source
var FreePageHintingConfig = NewJSONFlag("free-page-hinting-config", ldvalue.Null())

FreePageHintingConfig controls virtio-balloon free-page-hinting. "enabled" configures FreePageHinting=true on the balloon at install time (kernel-side eligibility is targeted separately via the LD context — the race fixed in https://lore.kernel.org/lkml/20240429125100.7393-1-david@redhat.com/ is on the hinting flow, gated by the per-use-case timeouts below). "pause"/"build" are pre-pause drain timeouts in ms keyed by SnapshotUseCase; missing/zero/negative disables the drain for that use case. "stop" and "stop_grace" bound the stop of a cycle that outlived its budget (see GetPrePauseHintConfig). Example: {"enabled": true, "pause": 500, "build": 0, "stop": 2000, "stop_grace": 100}

View Source
var IsolatedSchedulingHostsFlag = NewJSONFlag("isolated-scheduling-hosts", ldvalue.Null())

IsolatedSchedulingHostsFlag names the cluster hosts on the isolated side of the sandbox scheduling partition, as a JSON array of cluster host (node) IDs:

["node-a", "node-b"]

Null or empty (the default) leaves scheduling unpartitioned. The list is a policy, not a view of the fleet: it says nothing about which of those hosts are online, and hosts missing from the cluster simply never come up as candidates. Target it per cluster.

View Source
var LogsReadConfigFlag = NewBoolFlag("logs-read-config", logsReadConfigFallback())

LogsReadConfigFlag selects the backend used to read sandbox/build logs. false reads from Loki (unchanged behavior); true reads from the ClickHouse sandbox_logs table. The fallback comes from LOGS_READ_CONFIG and defaults to false, so a deployment without LaunchDarkly, or one whose LaunchDarkly has no value for the flag, reads where the variable says; a LaunchDarkly value wins when there is one.

View Source
var LogsWriteConfigFlag = NewJSONFlag("logs-write-config", ldvalue.Null())

LogsWriteConfigFlag controls where sandbox/external logs are written, so operators can retarget log destinations from LaunchDarkly without a redeploy.

Shape (every key optional):

{
  "mode": "primary_only" | "primary_and_shadow",
  "primary_url": "http://localhost:30006",
  "shadow_urls": ["http://localhost:4321/logs"],
  "timeout_ms": 2000,
  "max_inflight_shadow_writes": 1024
}

A key present in the flag overrides the deployment default for that field; an absent (or null) key falls through to it:

mode                        LOGS_WRITE_MODE, else "primary_only"
primary_url                 LOGS_COLLECTOR_ADDRESS
shadow_urls                 LOGS_WRITE_SHADOW_URLS (comma-separated)
timeout_ms                  LOGS_WRITE_TIMEOUT_MS, else 2000
max_inflight_shadow_writes  LOGS_WRITE_MAX_INFLIGHT_SHADOW_WRITES, else 1024

Semantics:

  • null/missing/non-object -> the deployment defaults alone.
  • "primary_only" -> write to the primary URL only.
  • "primary_and_shadow" -> write to the primary URL; fire-and-forget the shadow URLs (shadow failures never affect the primary result).
  • An empty primary_url falls through like an absent one.
  • timeout_ms or max_inflight_shadow_writes <= 0 falls through; a timeout above the maximum is clamped.
  • A present but invalid value (unknown mode, a non-string or unsafe URL, shadow_urls that is not an array of <= maxLogWriteShadowURLs strings) invalidates the whole flag -> the deployment defaults alone.
  • URLs from the flag must be http URLs pointing at local/private hosts or allowed internal DNS suffixes. URLs from the environment are operator configuration and are not checked.

With the flag null and LOGS_WRITE_TIMEOUT_MS unset the timeout is 0: writes rely on the HTTP client's own timeout, as they did before this flag existed.

The defaults are runtime env values the flag cannot know, so the default is Null() and the resolver substitutes them (see LogWriteDefaultsFromEnv).

View Source
var RateLimitConfigFlag = NewJSONFlag("rate-limit-config", ldvalue.Null())

RateLimitConfigFlag provides per-team rate limit overrides. JSON format:

{
  "/sandboxes/": {"rate": 50, "burst": 100},
  "/sandboxes/:sandboxID/pause": {"rate": 10, "burst": 20}
}

Entries set per-team route limits; routes absent from the flag remain unlimited.

View Source
var RateLimitDeleteMode = NewStringFlag("rate-limit-delete-mode", APIGroupRateLimitDisabled)
View Source
var RateLimitV2Mode = NewStringFlag("rate-limit-v2-mode", APIGroupRateLimitDisabled)
View Source
var ReclaimConfigFlag = NewJSONFlag("guest-pause-reclaim", ldvalue.Null())

ReclaimConfigFlag holds per-step caps in milliseconds for the pre-pause reclaim chain. Missing/zero/negative values disable the step. Example: {"sync":500,"drop_caches":200,"compact_memory":1000,"fstrim":500}

View Source
var SandboxPauseRateLimitFlag = NewJSONFlag("sandbox-pause-rate-limit", ldvalue.Null())

SandboxPauseRateLimitFlag caps explicit pause requests per sandbox:

{"limit": 5, "period_s": 60}

period_s must be 1 to 600, which keeps every limiter key in Redis for at most ten minutes. Null or an invalid value leaves pauses unlimited.

View Source
var TCPFirewallEgressThrottleConfig = NewJSONFlag("tcpfirewall-egress-throttle-config", ldvalue.FromJSONMarshal(map[string]any{
	"ops":       map[string]any{"bucketSize": -1, "oneTimeBurst": 0, "refillTimeMs": 1000},
	"bandwidth": map[string]any{"bucketSize": -1, "oneTimeBurst": 0, "refillTimeMs": 1000},
}))

TCPFirewallEgressThrottleConfig controls per-sandbox egress throttling via Firecracker's VMM-level token bucket rate limiters on the network interface. Structure mirrors the Firecracker RateLimiter API: two independent token buckets. Set bucketSize to -1 to disable a bucket.

Ops bucket (packets): effective rate = ops.bucketSize * 1000 / ops.refillTimeMs ops/s. Bandwidth bucket (bytes): effective rate = bandwidth.bucketSize * 1000 / bandwidth.refillTimeMs bytes/s.

View Source
var TrackedTemplatesForMetrics = NewJSONFlag("tracked-templates-for-metrics", ldvalue.FromJSONMarshal(defaultTrackedTemplates))

TrackedTemplatesForMetrics is a JSON flag that defines which template aliases should be tracked in sandbox start time metrics. Templates not in this list will be grouped under "other" to reduce metric cardinality. JSON format: {"base": true, "code-interpreter-v1": true, ...}

Functions

func AddToContext

func AddToContext(ctx context.Context, contexts ...ldcontext.Context) context.Context

func BatcherContext

func BatcherContext(name string) ldcontext.Context

BatcherContext targets one named ClickHouse writer.

func ClusterContext

func ClusterContext(clusterID uuid.UUID) ldcontext.Context

func CompressFileTypeContext

func CompressFileTypeContext(fileType string) ldcontext.Context

func CompressUseCaseContext

func CompressUseCaseContext(useCase string) ldcontext.Context

func DeploymentEnvironmentContext

func DeploymentEnvironmentContext(name string) ldcontext.Context

func DetachContext

func DetachContext(ctx context.Context) context.Context

DetachContext returns a context that carries the flag contexts attached to ctx and nothing else of it: no deadline, cancellation or other value. A holder that evaluates flags with a request's targeting after the request has ended keeps this rather than the request context.

func EnvdUpgradeCandidate

func EnvdUpgradeCandidate(ctx context.Context, target, hostEnvdPath string) (candidate, reason string)

EnvdUpgradeCandidate maps an upgrade-target flag value to the binary it names, without probing it. Split out so the node-local binary cache can pre-warm the path a resume will actually ask for: a target naming a concrete version resolves to a staged sibling, not to hostEnvdPath, so warming hostEnvdPath alone leaves a version-pinned ramp with no pre-warm at all while still paying for one.

Returns ("", reason) when no upgrade applies -- the same reason strings resolveEnvdUpgradePath reports -- and (candidate, "") when there is a binary to probe. Everything past this point costs an exec of that binary, which is what the caller may want to keep off its critical path.

func EnvdUpgradeTarget

func EnvdUpgradeTarget(ctx context.Context, ff *Client) string

EnvdUpgradeTarget reads the live-upgrade target flag. Split from ResolveEnvdUpgrade so a caller can test the cheap, in-memory gates before the resolver stats up to three paths and execs the candidate binary for its version — work a resume that is going to be gated anyway should not pay for.

func EnvdUpgradeTargetDisabled

func EnvdUpgradeTargetDisabled(target string) bool

EnvdUpgradeTargetDisabled reports whether a target value names no target at all. One definition, shared with the resolver, so an early-out at the call site and the resolver's own "off" answer cannot disagree about which values mean disabled.

func FirecrackerVersionsFallback

func FirecrackerVersionsFallback(base map[string]string, raw string) (map[string]string, error)

FirecrackerVersionsFallback merges the FirecrackerVersionsEnv overrides in raw over base; base entries must derive to their key, overrides must parse; on error it returns a copy of base with the error.

func GetExtraCompatibleNodeModels

func GetExtraCompatibleNodeModels(ctx context.Context, ff *Client, contexts ...ldcontext.Context) map[string][]string

GetExtraCompatibleNodeModels reads ExtraCompatibleNodeModelsFlag. A null or malformed value returns nil; a malformed one is logged once per distinct value.

func GetIsolatedSchedulingHosts

func GetIsolatedSchedulingHosts(ctx context.Context, ff *Client, contexts ...ldcontext.Context) map[string]struct{}

GetIsolatedSchedulingHosts reads IsolatedSchedulingHostsFlag as a set. A value that is not an array of non-empty strings reads as empty, leaving scheduling unpartitioned rather than stranding every sandbox on a typo.

func GetTrackedTemplatesSet

func GetTrackedTemplatesSet(ctx context.Context, ff *Client) map[string]struct{}

GetTrackedTemplatesSet fetches the TrackedTemplatesForMetrics flag and returns it as a set for efficient lookup. Only keys with a truthy value are included; keys set to false are ignored.

func InstanceGroupContext

func InstanceGroupContext(instanceGroupName string) ldcontext.Context

func IsFreePageHintingEnabled

func IsFreePageHintingEnabled(ctx context.Context, ff *Client, contexts ...ldcontext.Context) bool

IsFreePageHintingEnabled reports whether FPH should be configured on the balloon at install time.

func OverrideBoolFlag

func OverrideBoolFlag(flag BoolFlag, value bool)

OverrideBoolFlag forces a bool flag to a specific value in the offline store. Only takes effect when LAUNCH_DARKLY_API_KEY is not set (i.e. dev/CLI tools).

func OverrideJSONFlag

func OverrideJSONFlag(flag JSONFlag, value ldvalue.Value)

OverrideJSONFlag forces a JSON flag to a specific value in the offline store. Only takes effect when LAUNCH_DARKLY_API_KEY is not set (i.e. dev/CLI tools).

func ResolveEnvdOfflineUpgrade

func ResolveEnvdOfflineUpgrade(
	ctx context.Context,
	ff *Client,
	builtWithVersion string,
	hostEnvdPath string,
	getVersion func(context.Context, string) (string, error),
	stat EnvdStatFunc,
	evalContexts ...ldcontext.Context,
) (path, version, reason string)

ResolveEnvdOfflineUpgrade is the offline-swap analog of ResolveEnvdUpgrade same pure decision, keyed on EnvdOfflineUpgradeTargetFlag so the offline path ramps independently of the live one. builtWithVersion is the snapshot's recorded envd version (there is no running envd at cold-boot swap time), so — unlike the live path, which keys on the reported LiveEnvdVersion — the built-with never advances across an upgrade and this resolver keeps returning the same target on every resume until a re-pause re-bakes the version (an accepted, idempotent per-resume re-fire).

func ResolveEnvdUpgrade

func ResolveEnvdUpgrade(
	ctx context.Context,
	target string,
	builtWithVersion string,
	hostEnvdPath string,
	getVersion func(context.Context, string) (string, error),
	stat EnvdStatFunc,
) (path, version, reason string)

ResolveEnvdUpgrade decides whether a resuming sandbox's envd should be swapped for a newer node-local build, per EnvdUpgradeTargetFlag, and returns the local path of the target binary ("" = no upgrade). It is the resume-time analog of ResolveFirecrackerVersion.

hostEnvdPath is the promoted binary (cfg HostEnvdPath, e.g. /fc-envd/envd); versioned binaries live beside it as envd.<version> (legacy uploads: envd.<sha>). getVersion resolves a binary's baked version (orchestrator's build/core/envd.GetEnvdVersion) — it is injected so this shared package does not depend on the orchestrator.

The "should we upgrade?" test compares baked version *strings* (built-with vs the target's version). That holds as long as every upgrade target bakes a distinct version. A published build does: it bakes its release identity (LINK_VERSION), the SemVer of an envd release or the per-commit auto-deploy identity of any other main commit. A build without one bakes packages/envd/pkg/version.go, which release-please moves only once per envd release (nobody bumps it by hand), so two such builds cut between releases compare equal and a swap between them would be skipped. It returns the target binary's path and baked version ("" path = no upgrade), plus a reason for the no-upgrade case — off | not_staged | invalid_target | getversion_failed | same_version | downgrade | source_stalled, and "" when an upgrade IS returned — so the caller can tell a benign no-op (off / same_version) from a misconfigured target (not_staged from a bad SHA, a target that is not a bare identifier, getversion_failed, a refused downgrade) and from a mount that did not answer in time (source_stalled).

stat is how the candidate paths are checked; nil means os.Stat. The mount can stall a metadata lookup indefinitely, so a caller on the resume path passes a bounded stat.

func ResolveFirecrackerVersion

func ResolveFirecrackerVersion(ctx context.Context, ff *Client, buildVersion string) string

ResolveFirecrackerVersion resolves the firecracker version using the FirecrackerVersions feature flag. The stored version's LD key (e.g. "v1.12" for "v1.12.1_210cbac", "v1.14-0" for "v1.14-0.1.0") is looked up in the flag map; on parse failure or a missing key the stored version is returned unchanged.

func SandboxContext

func SandboxContext(sandboxID string) ldcontext.Context

func ServiceContext

func ServiceContext(serviceName string) ldcontext.Context

func TeamContext

func TeamContext(teamID string) ldcontext.Context

func TeamContextWithName

func TeamContextWithName(teamID, teamName string) ldcontext.Context

func TemplateContext

func TemplateContext(templateID string) ldcontext.Context

func UserContext

func UserContext(userID string) ldcontext.Context

func VolumeContext

func VolumeContext(volumeName string) ldcontext.Context

Types

type BlockDriveThrottleConfigValue

type BlockDriveThrottleConfigValue struct {
	Ops       TokenBucketConfig
	Bandwidth TokenBucketConfig
}

BlockDriveThrottleConfigValue holds the parsed values of BlockDriveThrottleConfig.

func GetBlockDriveThrottleConfig

func GetBlockDriveThrottleConfig(ctx context.Context, ff *Client) BlockDriveThrottleConfigValue

GetBlockDriveThrottleConfig fetches and parses the BlockDriveThrottleConfig flag.

type BoolFlag

type BoolFlag struct {
	// contains filtered or unexported fields
}

func NewBoolFlag

func NewBoolFlag(name string, fallback bool) BoolFlag

func (BoolFlag) Fallback

func (f BoolFlag) Fallback() bool

func (BoolFlag) Key

func (f BoolFlag) Key() string

func (BoolFlag) String

func (f BoolFlag) String() string

type Client

type Client struct {
	// contains filtered or unexported fields
}

func NewClient

func NewClient(deploymentEnvironment, serviceName, serviceVersion string, opts ...Option) (*Client, error)

NewClient creates a client that adds a DeploymentEnvironmentKind context and, when serviceName is not empty, a ServiceKind context to every evaluation. The same names, with serviceVersion, identify the process as a LaunchDarkly application; see applicationInfo.

func NewClientWithDatasource

func NewClientWithDatasource(source *ldtestdata.TestDataSource) (*Client, error)

func NewClientWithLogLevel

func NewClientWithLogLevel(deploymentEnvironment, serviceName, serviceVersion string, logLevel ldlog.LogLevel, opts ...Option) (*Client, error)

NewClientWithLogLevel creates a client with a specific log level. Use ldlog.Error to suppress INFO/WARN logs in CLI tools.

func (*Client) BoolFlag

func (c *Client) BoolFlag(ctx context.Context, flag BoolFlag, contexts ...ldcontext.Context) bool

func (*Client) BoolFlagOverride

func (c *Client) BoolFlagOverride(ctx context.Context, flag BoolFlag, contexts ...ldcontext.Context) (bool, bool)

BoolFlagOverride returns whether a flag was successfully evaluated. Callers with different legacy defaults can distinguish an explicit false from a fallback.

func (*Client) Close

func (c *Client) Close(ctx context.Context) error

func (*Client) IntFlag

func (c *Client) IntFlag(ctx context.Context, flag IntFlag, contexts ...ldcontext.Context) int

func (*Client) IntFlagOverride

func (c *Client) IntFlagOverride(ctx context.Context, flag IntFlag, contexts ...ldcontext.Context) (int, bool)

IntFlagOverride returns the flag's value and whether LaunchDarkly served it. On a failed evaluation — a client in LaunchDarkly's offline mode or not yet initialised, a value of the wrong type — the value is the fallback and the second result is false, so a caller can tell a served value from one equal to the fallback. A key the environment does not define counts as served at the fallback: nobody has chosen a value, which is what the fallback stands for, and an environment that never creates the flag is not failing. The keyless client (the package's offline store) serves every NewIntFlag flag at its fallback, which counts as served too.

func (*Client) IntFlagWithError

func (c *Client) IntFlagWithError(ctx context.Context, flag IntFlag, contexts ...ldcontext.Context) (int, error)

IntFlagWithError uses the fallback only when no flag value is available. Invalid values and other evaluation failures are returned as errors.

func (*Client) JSONFlag

func (c *Client) JSONFlag(ctx context.Context, flag JSONFlag, contexts ...ldcontext.Context) ldvalue.Value

func (*Client) Live

func (c *Client) Live() bool

Live reports whether flag values can change at runtime.

func (*Client) RegisterContextProvider

func (c *Client) RegisterContextProvider(provider ContextProvider)

RegisterContextProvider registers a provider whose contexts are appended to every flag evaluation.

func (*Client) StringFlag

func (c *Client) StringFlag(ctx context.Context, flag StringFlag, contexts ...ldcontext.Context) string

func (*Client) StringFlagOverride

func (c *Client) StringFlagOverride(ctx context.Context, flag StringFlag, contexts ...ldcontext.Context) (string, bool)

StringFlagOverride returns the value and whether the client supplied a variation, distinguishing a configured fallback value from a failed evaluation.

func (*Client) StringReader

func (c *Client) StringReader() StringReader

StringReader returns a reader over this client; a nil client's reader always answers the fallback.

func (*Client) WatchFlag

func (c *Client) WatchFlag(key string) (<-chan struct{}, func())

WatchFlag delivers on every change to the flag's configuration, whatever value any one context evaluates to, so a caller whose evaluations differ by context re-evaluates each of them on a change; changes that arrive while one is pending fold into it. The returned function ends the delivery and closes the channel.

func (*Client) WatchJSONFlag

func (c *Client) WatchJSONFlag(ctx context.Context, flag JSONFlag, contexts ...ldcontext.Context) (<-chan interfaces.FlagValueChangeEvent, func())

type Config

type Config struct {
	// DeploymentEnvironment is the OpenTelemetry deployment.environment value
	// of this process, for example "staging".
	DeploymentEnvironment string `env:"DEPLOYMENT_ENVIRONMENT"`
}

Config identifies the place a process runs in. Services embed it in their configuration struct, so the environment parser fills it with the rest.

type ContextProvider

type ContextProvider func(ctx context.Context) ldcontext.Context

ContextProvider supplies an additional LD context on every flag evaluation. Services register providers to inject specific contexts without leaking that specificity into the shared client.

type EnvdStatFunc

type EnvdStatFunc func(ctx context.Context, path string) (os.FileInfo, error)

EnvdStatFunc stats an envd upgrade candidate on the host mount.

type HintStopConfig

type HintStopConfig struct {
	// Timeout bounds the stop; zero leaves such a cycle running, which is the
	// behaviour before the stop existed and the rollback lever for it.
	Timeout time.Duration
	// Grace is how long the stop waits for a guest that has not echoed the
	// cycle's command before taking it to have never read it.
	Grace time.Duration
}

HintStopConfig bounds the stop of a hinting cycle the host stopped waiting for; every hinting drain shares it ("stop", "stop_grace" in FreePageHintingConfig, milliseconds).

type IntFlag

type IntFlag struct {
	// contains filtered or unexported fields
}

func NewIntFlag

func NewIntFlag(name string, fallback int) IntFlag

func (IntFlag) Fallback

func (f IntFlag) Fallback() int

func (IntFlag) Key

func (f IntFlag) Key() string

func (IntFlag) String

func (f IntFlag) String() string

type JSONFlag

type JSONFlag struct {
	// contains filtered or unexported fields
}

func NewJSONFlag

func NewJSONFlag(name string, fallback ldvalue.Value) JSONFlag

func (JSONFlag) Fallback

func (f JSONFlag) Fallback() ldvalue.Value

func (JSONFlag) Key

func (f JSONFlag) Key() string

func (JSONFlag) String

func (f JSONFlag) String() string

type LogWriteConfig

type LogWriteConfig struct {
	// PrimaryURL is the synchronous, success-controlling destination.
	PrimaryURL string
	// ShadowURLs are best-effort, fire-and-forget destinations.
	ShadowURLs []string
	// Timeout bounds each individual log write request.
	Timeout time.Duration
	// MaxInflightShadowWrites bounds concurrent best-effort shadow writes.
	MaxInflightShadowWrites int64
}

LogWriteConfig is the resolved, validated log write routing configuration.

func ResolveLogWriteConfig

func ResolveLogWriteConfig(ctx context.Context, ff *Client, defaults LogWriteDefaults, contexts ...ldcontext.Context) LogWriteConfig

ResolveLogWriteConfig reads LogsWriteConfigFlag and merges it over defaults: each key the flag sets wins, each key it leaves out takes the default. On a missing/malformed/unsafe flag it returns the defaults alone.

type LogWriteConfigResolver

type LogWriteConfigResolver struct {
	// contains filtered or unexported fields
}

LogWriteConfigResolver caches the resolved LogWriteConfig for a short TTL so callers on hot log-write paths avoid evaluating LaunchDarkly on every line. It is safe for concurrent use.

func NewLogWriteConfigResolver

func NewLogWriteConfigResolver(ff *Client, defaults LogWriteDefaults) *LogWriteConfigResolver

NewLogWriteConfigResolver builds a resolver that caches LogsWriteConfigFlag evaluations, merged over defaults, for a short TTL. A nil ff is supported: Resolve then always returns the defaults alone.

func (*LogWriteConfigResolver) Resolve

Resolve returns the cached LogWriteConfig, refreshing it via ResolveLogWriteConfig when the cache is empty or expired. Behavior for null/malformed/unsafe flag values is identical to ResolveLogWriteConfig.

type LogWriteDefaults

type LogWriteDefaults struct {
	Mode                    string
	PrimaryURL              string
	ShadowURLs              []string
	Timeout                 time.Duration
	MaxInflightShadowWrites int64
}

LogWriteDefaults is the deployment's log write routing. Each field applies when LogsWriteConfigFlag leaves the matching key out; a zero field is unset.

func LogWriteDefaultsFromEnv

func LogWriteDefaultsFromEnv(primaryURL string) LogWriteDefaults

LogWriteDefaultsFromEnv reads the LOGS_WRITE_* variables. primaryURL is the collector address (LOGS_COLLECTOR_ADDRESS). Unparseable or non-positive values are ignored, leaving that field unset.

type Option

type Option func(*options)

Option configures NewClient and NewClientWithLogLevel.

func WithStartOnInitTimeout

func WithStartOnInitTimeout() Option

WithStartOnInitTimeout keeps the client when LaunchDarkly has not answered within waitForInit: it is Live and serves fallbacks until the stream connects, then follows the flags. A permanent failure, such as a rejected SDK key, still fails. Opt in only where running on fallbacks is safer than not starting.

type PeriodicHintingConfig

type PeriodicHintingConfig struct {
	Interval        time.Duration
	Timeout         time.Duration
	QuietAfterStart time.Duration
	// ObserveOnly ticks and records the interval baseline but never hints: a
	// control cohort on hinting templates.
	ObserveOnly       bool
	SilentRuns        int
	UnresponsiveRetry time.Duration
	HostSlots         int
	Stop              HintStopConfig
}

PeriodicHintingConfig is the "periodic" object of FreePageHintingConfig: host-driven free-page-hinting runs that replace continuous free-page reporting. Example:

{"enabled": true, "pause": 500, "stop": 2000, "stop_grace": 100,
 "periodic": {"interval": 15000, "timeout": 500, "quiet_after_start": 10000}}

interval <= 0 disables the loop, and so does an interval under a second (the field is in milliseconds; a value typed in seconds would be a tight loop against every guest); timeout <= 0 falls back to 500 ms; quiet_after_start clamps at 0. The stop settings are the shared top-level ones. observe_only keeps the loop ticking and recording the interval baseline without ever hinting: the control cohort a ramp is read against.

silent_runs is how many runs in a row a guest may sit out (never echoing the command, or a start FC refuses) before the loop backs off to unresponsive_retry between attempts; 0 never backs off. host_slots bounds the runs in flight on one host; 0 is unbounded.

func GetPeriodicHintingConfig

func GetPeriodicHintingConfig(ctx context.Context, ff *Client, contexts ...ldcontext.Context) PeriodicHintingConfig

GetPeriodicHintingConfig reads the periodic block; missing fields take the defaults above, a missing block or interval <= 0 disables the loop.

func (PeriodicHintingConfig) Enabled

func (c PeriodicHintingConfig) Enabled() bool

type PrePauseHintConfig

type PrePauseHintConfig struct {
	// Timeout is the drain budget; zero disables the drain for the use case.
	Timeout time.Duration
	Stop    HintStopConfig
}

PrePauseHintConfig is what the pre-pause drain reads from FreePageHintingConfig for one SnapshotUseCase.

func GetPrePauseHintConfig

func GetPrePauseHintConfig(ctx context.Context, ff *Client, useCase string, contexts ...ldcontext.Context) PrePauseHintConfig

GetPrePauseHintConfig reads the drain budget for useCase ("pause", "build") and the shared stop settings. Example: {"enabled": true, "pause": 500, "build": 0, "stop": 2000, "stop_grace": 100}

type ReclaimConfig

type ReclaimConfig struct {
	Sync          time.Duration
	DropCaches    time.Duration
	CompactMemory time.Duration
	Fstrim        time.Duration
}

func GetReclaimConfig

func GetReclaimConfig(ctx context.Context, ff *Client, contexts ...ldcontext.Context) ReclaimConfig

type StringFlag

type StringFlag struct {
	// contains filtered or unexported fields
}

func NewStringFlag

func NewStringFlag(name string, fallback string) StringFlag

func (StringFlag) Fallback

func (f StringFlag) Fallback() string

func (StringFlag) Key

func (f StringFlag) Key() string

func (StringFlag) String

func (f StringFlag) String() string

type StringReader

type StringReader struct {
	// contains filtered or unexported fields
}

StringReader evaluates a string flag by key with its caller's fallback and the process contexts, for a package that takes a small reader interface rather than this package's flag types.

It never logs: it is read on hot paths, and the typed flag methods warn on every evaluation of a key the client does not hold.

func (StringReader) String

func (r StringReader) String(ctx context.Context, key, fallback string) string

String returns the flag's value, or fallback when the flag is missing or not a string. A keyless client serves only the flags registered here and an unconnected one serves nothing, so neither is evaluated.

type TCPFirewallEgressThrottleConfigValue

type TCPFirewallEgressThrottleConfigValue struct {
	Ops       TokenBucketConfig
	Bandwidth TokenBucketConfig
}

TCPFirewallEgressThrottleConfigValue holds the parsed values of TCPFirewallEgressThrottleConfig.

func GetTCPFirewallEgressThrottleConfig

func GetTCPFirewallEgressThrottleConfig(ctx context.Context, ff *Client) TCPFirewallEgressThrottleConfigValue

GetTCPFirewallEgressThrottleConfig fetches and parses the TCPFirewallEgressThrottleConfig flag.

type TokenBucketConfig

type TokenBucketConfig struct {
	BucketSize   int64
	OneTimeBurst int64
	RefillTimeMs int64
}

TokenBucketConfig holds parameters for a single Firecracker token bucket. BucketSize < 0 disables the bucket.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL