Namespaces are Kubernetes' primary organizational unit. Get them right early and your team scales smoothly. Get them wrong and you're refactoring under pressure.
Strategy 1: by environment
The simplest approach — one namespace per environment:
development/
staging/
production/
Pros:
- Easy to understand
- Simple RBAC rules (developers get full access to dev, read-only to prod)
- Clear deployment pipeline: dev → staging → production
Cons:
- Doesn't scale when you have 20+ microservices
- All services share resource quotas per environment
- Hard to isolate team resources
Best for: Small teams (2-5 engineers) with fewer than 10 services.
Strategy 2: by team
One namespace per team:
team-platform/
team-payments/
team-notifications/
team-analytics/
Pros:
- Teams own their namespace and resources
- Resource quotas per team prevent one team from starving others
- RBAC maps cleanly to team structure
Cons:
- Cross-team service discovery requires fully qualified DNS names
- Shared services (databases, message queues) need their own namespace
- Environment separation requires combining with another strategy
Best for: Medium teams (5-20 engineers) organized by domain.
Strategy 3: by team and environment
The hybrid approach — combine team and environment:
payments-dev/
payments-staging/
payments-prod/
platform-dev/
platform-staging/
platform-prod/
Pros:
- Full isolation between teams AND environments
- Granular resource quotas and RBAC
- Clear ownership at every level
Cons:
- Namespace explosion (teams × environments)
- More complex NetworkPolicy rules
- Deployment tooling needs to be namespace-aware
Best for: Larger teams (20+ engineers) with strict compliance requirements.
Essential namespace practices
Regardless of strategy, follow these practices:
Resource quotas
apiVersion: v1
kind: ResourceQuota
metadata:
name: team-quota
namespace: team-payments
spec:
hard:
requests.cpu: "10"
requests.memory: "20Gi"
limits.cpu: "20"
limits.memory: "40Gi"
pods: "50"
Limit ranges
Set defaults so pods without resource specs don't run as BestEffort:
apiVersion: v1
kind: LimitRange
metadata:
name: default-limits
namespace: team-payments
spec:
limits:
- default:
cpu: "500m"
memory: "512Mi"
defaultRequest:
cpu: "100m"
memory: "128Mi"
type: Container
Network policies
Start with a deny-all policy and explicitly allow what's needed:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: deny-all
namespace: team-payments
spec:
podSelector: {}
policyTypes:
- Ingress
- Egress
Navigating namespaces
As namespace count grows, quick navigation becomes critical. A visual tool that lets you switch between namespaces instantly and see resources across multiple namespaces at once saves significant context-switching time.
The right namespace strategy grows with your team. Start simple, add structure as needed, and always have visibility into what's running where.