Flags & @PipeFlag
Flags are remotely controllable variables that you can change from the PipeKit dashboard without shipping an app update. Think of them as feature flags with real-time push delivery.
What is a Flag?
A flag is a typed Swift property annotated with @PipeFlag that registers itself with PipeKit at app launch. The property works exactly like a normal variable, but its value can be overridden remotely from the dashboard in real-time.
Flags are safe by design. They only accept values that match the declared type. If the PipeKit server is unreachable, the compiled default value is used. Your app always works, with or without a connection.
Declaring a Flag
Use the @PipeFlag macro on a stored property with a default value. Supported types are Bool, Int, Double, and String.
import PipeKitSDKclass AppFlags {@PipeFlag var isMaintenanceMode = false@PipeFlag var maxRetries = 3@PipeFlag var refreshInterval = 30.0@PipeFlag var welcomeMessage = "Hello!"}
Custom Display Names
By default, the property name is used as the flag identifier in the dashboard. You can provide a custom display name for better readability.
@PipeFlag("api-endpoint")var apiEndpoint = "https://api.prod.com/v2"@PipeFlag("cdn-url")var cdnBaseURL = "https://cdn.pipekit.dev"
How It Works
The @PipeFlag macro transforms your stored property into a computed property backed by PipeKit's FlagStore. Here's the lifecycle:
Registration
On app launch, the SDK reports all @PipeFlag properties to the PipeKit server with their names, types, and default values.
Sync
The server responds with any active overrides. These are applied to the local FlagStore immediately.
Real-time Push
When you change a flag value in the dashboard, the override is pushed to connected devices via WebSocket instantly.
Value Resolution
When your code reads the property, the FlagStore resolves the value using a priority chain: remote override > local override > compiled default.
Value Resolution Priority
When your code reads a flag property, the value is resolved in this order:
Remote overrideSet by an admin from the dashboard. Pushed via WebSocket or pulled via HTTP sync.Local overrideSet programmatically via the property setter. Useful for testing.Compiled defaultThe value in your source code. Always used as the fallback.Using Flags in Code
Read and write flags just like normal properties. No async, no callbacks, no special APIs.
let flags = AppFlags()// Reading — returns the current effective valueif flags.isMaintenanceMode {showMaintenanceBanner()}// Writing — sets a local override (does not push to server)flags.maxRetries = 5
Device Targeting
Flag overrides can target all devices or specific devices. This is useful for gradual rollouts, A/B testing, or debugging a specific user's device.
Global Override
Applies to all connected devices. Set from the dashboard by choosing "All Devices" when pushing an override.
Device-Specific Override
Applies only to selected devices. Choose "Specific Devices" in the dashboard and pick the target devices from the list.
Managing Flags in the Dashboard
The Flags page in the dashboard shows all registered flags for your app. For each flag you can see:
- Flag name and identifier
- Type badge (Bool, Int, Double, String)
- Compiled default value
- Current override value (if any)
- Device targeting status
- Last reported timestamp
Click the edit icon to push an override, or the trash icon to remove it. When you remove an override, all devices revert to the compiled default. Changes are pushed in real-time via WebSocket.
Supported Types
Bool
true / false
Int
0, 42, -1
Double
3.14, 0.5
String
"hello"
Best Practices
Always provide a sensible default
Your app should work perfectly with just the compiled defaults. Remote overrides are enhancements, not requirements.
Use Bool flags for kill switches
A @PipeFlag var isMaintenanceMode = false gives you an instant kill switch from the dashboard.
Group related flags
Keep flags in dedicated classes (e.g., AppFlags, NetworkFlags) for better organization.
Don't use flags for secrets
Flag values are visible in the dashboard and transmitted over the network. Use them for configuration, not credentials.
