For platform teams building cloud-native software, the local developer workstation has evolved from a productivity tool into an operational risk. Developers lose valuable time wrestling with local VM setups or hunting down "works on my machine" bugs. As local environments diverge, architectural friction stalls engineering progress and pulls platform teams into endless troubleshooting.
Moving compute, tooling, and environment definitions onto Red Hat OpenShift Dev Spaces shifts workloads into governed, containerized workspaces running directly on the cluster. This installment covers the platform foundation needed to run containerized workspaces safely at scale while protecting cluster performance and etcd health.
Moving past the limitations of local development environments
Modern application architectures rely heavily on containerized microservices, specialized runtimes, and complex dependency graphs. Forcing these distributed topologies onto individual developer laptops frequently breaks down, leading to persistent build failures and environment drift between local laptops and cluster nodes.
Strict zero trust security policies often bar developers from running container engines like Podman or Docker with elevated local privileges. To work around these restrictions, engineering teams frequently resort to heavy local virtual machines, dedicated remote build servers, or nested container-in-VM setups that add latency and maintenance overhead without solving the underlying problem.
This fragmented approach introduces 3 concrete platform risks:
- Production-parity risk: Local environments inevitably drift from one another and from production baselines—a dependency version, an environment variable, a base image—until a bug existing only locally slips past code review and surfaces late in quality assurance (QA), or worse, in production.
- Slow time-to-first-commit: A newly onboarded engineer often spends days configuring local dependencies and runtimes before pushing their first line of code.
- Unmanaged security exposure: A misconfigured local proxy, an unpatched command-line interface (CLI) tool, or a credential left in a local
.envfile becomes a risk the platform team has no visibility into and no way to remediate at scale—multiplied across every laptop in the organization.
Shifting to centralized developer governance
The industry's answer to this is the cloud development environment (CDE): an operating model where compute, tooling, and configuration move off the laptop entirely and onto a governed, centrally managed platform. Red Hat OpenShift Dev Spaces is a direct implementation of that model. The developer's workspace runs as a container directly on the OpenShift platform, with runtimes, tools, and project configuration declared as code in a version-controlled devfile—so every developer works from an identical, reproducible environment instead of a hand-maintained local one.
Operating Red Hat OpenShift Dev Spaces across an enterprise requires balancing developer flexibility with platform governance across 3 main pillars: automation, integration, and security.
We built this guide from real production rollouts on OpenShift 4.20.16 and OpenShift Dev Spaces 3.26. Here is what we learned along the way—and what you should look out for during your own deployment. As Red Hat publishes new versions, engineering teams add features and deprecate some functionality. Refer to the specific version of the OpenShift Dev Spaces documentation at the time of installation.
Platform blueprint: Multi-tenant namespace isolation
In a production-ready enterprise deployment, a critical architectural decision involves isolating OpenShift Dev Spaces components across multiple namespaces. A naive installation often relies on a single namespace for both the cluster logic and the running servers. Under high-scale multi-tenancy, however, this tightly coupled architecture introduces severe operational risks.
To protect platform integrity, the architecture distributes cluster workloads across 4 discrete, functional namespaces, as illustrated in Figure 1:
openshift-devspaces(the control zone): Houses the global Red Hat OpenShift Dev Spaces operator, the DevWorkspace operator, cluster-wide configuration definitions, and platform-level maintenance cron jobs.devspaces-checluster(the core server zone): Contains the primaryCheClustercustom resource (CR) instance, the management dashboard, the Traefik-based routing gateway, the Open Authorization (OAuth) authentication proxy, and the plug-in registry—the internal proxy that fronts the OpenVSX server for workspace extension requests.devspaces-openvsx(the secure asset zone): An isolated, network-restricted boundary containing the internal OpenVSX server binaries, its PostgreSQL backend, and the curated extension cache the plug-in registry above pulls from.<username>-devspaces(the sandbox workspace zone): Individual, dynamically mapped namespaces allocated strictly to single developers to provide complete compute, storage, and network isolation between users. Because each developer's namespace is provisioned independently, it also carries the metadata needed for cost allocation and chargeback.

Each of these boundaries exists for a distinct reason: the control zone must remain untouched by workload-level changes, the core server zone must be shielded from the operator's own reconciliation behavior, the secure asset zone must stay network-isolated from public extension marketplaces, and the sandbox zone must guarantee that 1 developer's workspace can never see or affect another's.
The namespace collision risk: Protecting operator configs
Placing the CheCluster custom resource inside the core operator namespace (openshift-devspaces) creates a hidden conflict that directly threatens platform stability. When the core platform operator shares a namespace with the specific cluster instance, the operator's automated reconciliation loop takes precedence over custom parameters.
As a result, custom definitions placed within your DevWorkspaceOperatorConfig—such as tailored workspace pruning rules, specific security profiles, or idle timeouts—get silently overridden and reset to factory defaults during routine reconciliation.
Isolating the CheCluster custom resource inside its own dedicated namespace (devspaces-checluster) prevents this behavior entirely, verifying that your platform maintenance choices remain immutable.
Governing the workspace lifecycle: Provisioning, sizing, and cleanup
Running OpenShift Dev Spaces at scale requires treating workspaces as short-lived container workloads bounded by automatic timeouts and quotas, rather than persistent local setups. In an enterprise context, this lifecycle follows a precise timeline: explicit onboarding authorization, active-state sizing controls, and aggressive etcd cleanup routines.
Advanced authorization and access controls
Before provisioning a single workspace namespace, the platform must validate access at the cluster boundary. OpenShift Dev Spaces delegates user authentication entirely to OpenShift's own OAuth—the che-gateway component authenticates users via OpenID Connect (OIDC) through the built-in OpenShift OAuth2 proxy, so whatever identity provider your cluster is already configured with does the actual authenticating. On top of that, advancedAuthorization adds a 2nd, independent gate: a user must be in allowUsers or allowGroups, and not in denyUsers or denyGroups, to access the dashboard at all.
## Patched via pipeline to restrict access to authenticated Lightweight Directory Access Protocol/Active Directory (LDAP/AD) groups
spec:
networking:
auth:
advancedAuthorization:
allowGroups:
- G-ENTERPRISE-ADMINS
- G-PAYMENTS-TEAM-DEVSPACES
- G-CORE-ENG-DEVSPACES
allowUsers:
- individual-tester-01The reverse proxy gateway (che-gateway) uses an internal OAuth proxy sidecar to enforce session timeout limits. For production platforms, configure cookieExpireSeconds: 86400 (24 hours). This limits session token longevity and helps developers re-authenticate against the corporate identity manager daily.
Being a member of an authorized group only grants the right to request a workspace—it doesn't create a namespace on its own. That request flow, and what happens behind it, is where chargeback and cost governance get enforced.
Self-service namespace provisioning and chargeback
While OpenShift Dev Spaces can automatically create a namespace the moment a user logs in, you must disable auto-provisioning (autoProvision: false) at scale. The default, dynamic namespace creation path has no hook for applying enterprise cost-allocation labels, and—equally importantly—no hook for attaching a ResourceQuota or LimitRange to the namespace at creation time. Both have to exist from the moment the namespace is created, not patched in afterward.
To solve this, our architecture routes every request through an external self-service portal. When a team requests an environment, the portal provisions the namespace, attaches a LimitRange and ResourceQuota sized to that team's stated requirements, and stamps the namespace with the labels our chargeback model depends on—all in 1 atomic step:
apiVersion: v1
kind: Namespace
metadata:
name: jdoe-devspaces
labels:
app.kubernetes.io/part-of: che.eclipse.org # Mandatory lookup key
app.kubernetes.io/component: workspaces-namespace # Mandatory discovery key
dynatrace.com/inject: "false" # Application Performance Monitoring (APM) conflict suppression label
enterprise.com/cost-center: "CC-9011" # Chargeback label—adjust to your org's taxonomy
enterprise.com/line-of-business: "RETAIL-BANKING" # Line-of-business label—adjust to your org's taxonomy
annotations:
che.eclipse.org/username: "JDOE" # Case-sensitive matching criteriaThe gateway quota trap
Once namespaces carry a ResourceQuota requiring explicit limits on every container, workspace creation starts failing with an unrecoverable deployment condition:
Error creating devworkspace deployment: detected unrecoverable deployment condition:
Failed create pods '<podname>' is forbidden: failed quota: <resource quota name>:
must specify limits.cpu for che-gatewayThe root cause: The OpenShift Dev Spaces operator intentionally omits a CPU limit on the che-gateway container to prevent CPU throttling during active editing sessions (eclipse-che/che#22198). When a ResourceQuota forces limits on every pod in the namespace, che-gateway has none to offer, and OpenShift rejects the pod outright.
The fix is to explicitly set a CPU limit for the gateway container in the CheCluster CR:
spec:
devEnvironments:
gatewayContainer:
resources:
limits:
cpu: "500m"Caveat: It's tempting to assume the defaultContainerResources setting explained in Accurately setting requests, limits, and resource caps already covers this—it doesn't. That setting applies to every workspace container except the gateway. You must set the gateway's resources separately, exactly as shown in the previous code example, or the quota failure returns the moment defaultContainerResources is your only line of defense.
Accurately setting requests, limits, and resource caps
Once a namespace exists with its quota in place, the next question is how much of that quota any single workspace is allowed to consume. Developers, out of a reasonable fear of environment starvation, will routinely over-request compute resources. Because CPU is compressible but memory is not, over-provisioned memory requests are the more damaging of the 2—they lower compute density across your worker nodes even when the memory is never used.
To prevent this, use a 2-tier resource governance model:
spec:
devEnvironments:
# Tier 1: system-wide fallback for containers that don't define their own limits
defaultContainerResources:
requests:
cpu: "100m"
memory: "500Mi"
limits:
cpu: "500m"
memory: "2Gi"
# Tier 2: absolute ceiling enforced per container
containerResourceCaps:
requests:
cpu: "100m"
memory: "500Mi"
limits:
cpu: "4"
memory: "32Gi"Caveat: containerResourceCaps applies per individual container, not per workspace pod as a whole. If a developer's devfile defines a multi-container workspace—say, an application container, a database sidecar, and a separate tooling container—each one can independently claim resources up to the cap. A 3-container workspace can therefore consume up to 3 times the per-container ceiling. Platform teams should monitor actual cluster resource usage rather than assuming the cap bounds a workspace's total footprint.
Storage strategy and volume isolation
For development workloads, block storage outperforms shared network file systems. We use a per-workspace persistent volume claim (PVC) strategy backed by Ceph RADOS Block Device (RBD), giving every workspace an isolated 5 GiB persistent volume. This prevents cross-project storage pollution, produces clean reclamation on workspace deletion, and avoids data-affinity conflicts when a single developer runs multiple workspaces at once.
Automated cleanup and etcd preservation
Unused workspaces silently drain cluster resources. Automated cleanup is essential to keeping etcd healthy and operational. Long-term cluster stability depends heavily on the state footprint of etcd (the default etcd size is 2 GB), and Red Hat's own guidance for running OpenShift Dev Spaces at scale recommends staying under a maximum of 8 GB—exceeding it risks making the entire Kubernetes cluster unstable and unresponsive. Stopped workspaces still hold their state and metadata as live custom resources in etcd, and per that same Red Hat guidance, roughly 6,000 of these objects can consume around 2.5 GB of etcd storage on their own.
To keep the cluster within safe bounds, enable the workspace cleanup CronJob in the DevWorkspaceOperatorConfig, located in the openshift-devspaces control namespace:
apiVersion: controller.devfile.io/v1alpha1
kind: DevWorkspaceOperatorConfig
metadata:
name: devworkspace-operator-config
namespace: openshift-devspaces
config:
workspace:
cleanupCronJob:
enable: true
dryRun: false
retainTime: 2592000 # Deletes any workspace stopped for more than 30 days
schedule: "0 0 1 * *" # Runs on the 1st of every monthPair this monthly purge with inactivity idling in the CheCluster CR, so worker nodes aren't holding memory for workspaces nobody is actively using:
secondsOfInactivityBeforeIdling: 14400: Stops the workspace pod after 4 hours of complete inactivity.secondsOfRunBeforeIdling: -1: Disables total-runtime restrictions entirely so an active build or long-running process is never killed mid-cycle.
Building a governance-first foundation
Distributing control workloads across a 4-zone namespace topology isolates operational risk while giving developers predictable environments. Enforcing resource caps and automated cleanup rules at initial setup protects cluster stability, keeping the etcd footprint within safe limits before user adoption grows.
Once namespace isolation, memory caps, and cleanup routines are in place, the next step is connecting developers to internal tooling. In part 2, we'll cover automating corporate Git authentication, running a private extension registry, and delivering remote JetBrains IDE support across restricted networks.
Ready to configure your cluster? Try Red Hat OpenShift Dev Spaces.