Projects & Environments
Everything you build in Koolbase lives inside a project, and every project has one or more environments. Knowing what each one isolates is the difference between a clean dev/prod setup and accidentally mixing test data with real users.
The mental model
Project
The isolation boundary. It owns your data, files, server-side code, and secrets. Nothing crosses between projects — two projects are two separate worlds.
Environment
A configuration and rollout context inside a project. It has its own API keys, feature flags, remote config, and version policy — but it shares the project's data.
How it's structured
A project holds the shared resources at the top, with environments nested inside it. Every environment in the project reads and writes the same database, storage, and functions:
Project: StrideHx
├── Database (collections + records) ← shared by all environments
├── Storage (buckets + files) ← shared
├── Functions + Secrets ← shared
├── OAuth + SMS providers ← shared
│
├── Environment: dev
│ ├── API keys (public / secret)
│ ├── Feature flags
│ ├── Remote config
│ └── Version policy
│
└── Environment: prod
├── API keys (public / secret)
├── Feature flags
├── Remote config
└── Version policyImportant: environments do not create separate databases
What's scoped where
| Resource | Scope |
|---|---|
| Database — collections, records, access rules | Project |
| Storage — buckets, files | Project |
| Functions and function logs | Project |
| Secrets | Project |
| OAuth providers | Project |
| SMS / phone-auth providers | Project |
| Auth users and sessions | Project |
| Analytics and audit logs | Project |
| OTA / code push bundles | Project |
| Domains and messaging | Project |
| API keys (public / secret) | Environment |
| Feature flags | Environment |
| Remote config | Environment |
| Version policy | Environment |
The part that trips people up
Because project resources are shared across every environment in a project, environments are notdata or resource isolation boundaries. They isolate configuration and rollout behavior, not persistence.
Environments do not isolate data
Recommended setup
For true dev/prod separation, use separate projects — not separate environments. Two projects means two databases, two storage backends, two function runtimes: zero chance of test data touching production.
Organization: TechFinityEdge
├── Project: stridehx-dev ← development data, users, storage, functions
├── Project: stridehx-staging ← release-candidate testing
└── Project: stridehx-prod ← real production users and dataRule of thumb
Separate environments within a project when you want different flags, config, or version rules against the same data — for example, an internal beta key with experimental flags switched on.
Why not isolate data by environment?
Koolbase deliberately avoids putting multiple isolated worlds inside one shared datastore with anenvironment_id label. Real isolation should use separate underlying project resources. This keeps the mental model simple, prevents accidental cross-environment writes, and aligns with how serious platforms separate dev, staging, and production systems.
API keys
API keys are one of the few things scoped to the environment, not the project. Each environment has two:
pk_live_...Public KeyUsed in your Flutter app. Safe to include in client-side code. Passed to Koolbase.initialize(KoolbaseConfig(publicKey: ...)).
sk_live_...Secret KeyUsed for server-side API calls. Never expose this in client code or commit it to version control.
Key rotation
Selecting an environment in your app
Pass the right public key for each build flavor using a Dart compile-time variable. Map each flavor to the public key of the environment (or project) you're targeting:
import 'package:flutter/material.dart';
import 'package:koolbase_flutter/koolbase_flutter.dart';
export const metadata = {
title: 'Projects Environments',
description: 'Everything you build in Koolbase lives inside a project, and every project has one or more environments. Knowing what each one isolates is the difference bet...',
}
// Public key per target. For true dev/prod separation these come
// from separate projects (see Recommended setup above).
const koolbaseKeys = {
'production': 'pk_live_prod_key_here',
'staging': 'pk_live_staging_key_here',
'development': 'pk_live_dev_key_here',
};
void main() async {
WidgetsFlutterBinding.ensureInitialized();
// Switch with --dart-define=ENV=production
const env = String.fromEnvironment('ENV', defaultValue: 'development');
final publicKey = koolbaseKeys[env] ?? koolbaseKeys['development']!;
await Koolbase.initialize(KoolbaseConfig(
publicKey: publicKey,
baseUrl: 'https://api.koolbase.com',
));
runApp(const MyApp());
}Run or build against a specific target:
# Development (default)
flutter run
# Staging
flutter run --dart-define=ENV=staging
# Production build
flutter build apk --dart-define=ENV=productionDuplicating an environment
From the dashboard you can duplicate an existing environment. This copies its feature flags, flag rules, remote config values, and version policies into a new environment with fresh API keys — handy for an internal beta key with experimental flags switched on, running against the same project data.
What is and isn't copied
Keeping separate projects in sync
Separate projects give you strong isolation, but they also introduce parity drift: dev may have a flag, collection rule, or function version that prod does not. Koolbase handles this through promotion flows, not shared persistence.
Production-like testing without touching production
The Backend as Code tooling copies configuration only — collection schemas and access rules, plus environment config (feature flags, remote config, and version policies). It does not copy records, secrets, OAuth/SMS credentials, API keys, or function code — deploy your functions to each project directly.