The Plan vs. Reality
The real problem was our namespace architecture. We'd designed this beautiful parent-child hierarchy:
engineering/
├── team-alpha/
├── team-beta/
research/
├── lab-1/
├── lab-2/
Looked clean in diagrams. Worked terribly in practice.
What Broke First
Problem 1: Permission inheritance was a minefield
Team Alpha couldn't understand why their policies sometimes worked and sometimes didn't. Turns out, parent namespace policies were interfering in ways nobody expected.
Created a policy in engineering/? Congrats, it now affects engineering/team-alpha/ in weird ways.
Problem 2: Mental overhead
Support conversation:
Team: "Our secret isn't working"
Me: "Which namespace?"
Team: "Uh... the team one?"
Me: "Parent or child?"
Team: "What's the difference?"
Every. Single. Time.
Problem 3: Automation nightmare
Writing scripts that work across parent AND child namespaces meant handling two different permission models. Code got messy fast:
This got old real quick
if is_parent_namespace(ns):
apply_parent_logic()
else:
apply_child_logic()
check_parent_inheritance()
pray_it_works()
The Breaking Point
I was onboarding a new team. Simple task: create their namespace, set up AppRole auth, done.
Except their parent namespace had conflicting policies. Their child namespace inherited permissions they didn't need. Auth setup failed in ways the error messages didn't explain.
Took me 3 hours to debug what should've been a 10-minute task.
That's when I talked to the team: "What if we just... stopped doing this?"
The Solution: Go Flat
We killed the hierarchy. New model:
team-alpha/
team-beta/
lab-1/
lab-2/
Need logical grouping? Use naming conventions:
eng_team-alpha/
eng_team-beta/
research_lab-1/
research_lab-2/
Underscores instead of slashes. Flat instead of nested.
What Changed
Onboarding went from 3 hours to 15 minutes
One namespace model. One set of policies. No inheritance surprises.
Support tickets dropped
Teams understood their namespace. No more "which namespace am I in?" questions.
Automation got stupid simple
No special cases. No inheritance checks. Just works.
Policies became predictable
What you write is what you get. No parent namespace secretly modifying things.
The Migration
Wasn't instant. We had production services in nested namespaces.
Phase 1: New namespaces use flat model only
Phase 2: Migrate low-risk teams first
Phase 3: Production migrations during maintenance windows
Phase 4: Deprecate parent/child model entirely
Took 3 months. Worth every minute.
The Pushback
"But we lose organizational structure!"
No, you don't. Use naming: dept_team_project. You can still grep, filter, and organize.
"What about RBAC across departments?"
Use Vault groups and entity aliases. Group-based permissions work better than namespace inheritance anyway.
"HashiCorp docs show parent/child namespaces!"
Docs show what's possible, not what's practical at scale. We learned the hard way.
When Nested Namespaces Make Sense
Look, I'm not saying nested namespaces are always wrong. They work if:
You have <10 namespaces total
Your team deeply understands Vault internals
You actually need different permission models per layer
We had 50+ namespaces and growing. Engineering teams, not Vault experts. Flat was the right call.
What I'd Tell My Past Self
"That pretty hierarchy in your architecture diagram? Users don't care. They want their secrets to work. Keep it simple."
Complexity is seductive in infrastructure design. Resist it.
The Vault Philosophy We Learned
Vault's "deny by default" model is powerful but unforgiving. Every layer of abstraction (like nested namespaces) adds opportunities for unexpected denials.
Simpler architecture = fewer surprises = happier teams.
Try This
If you're using nested namespaces, run this check:
bash# How many support tickets mention "namespace" or "permission denied"?
If it's more than 10% of your Vault tickets, consider flattening.
Your future self will thank you.
Top comments (0)