How a conference talk, a hardcoded branch, and too many deployment requests led me to ephemeral environments.
Remember how it started?
I was at a conference, volunteering.
Someone said "ephemeral," and I got hooked.
Remember when I fell in love?
I do.
April. NDC Sydney.
I wasn't on stage, or even there as a regular attendee.
I was volunteering.
And somewhere in between, I ended up in a talk called:
"Ephemeral Environments: Easier Said Than Spun"
And I fell for it.
Not a person.
An idea that could kill the most annoying sentence in my job.
To explain why it hit so hard, I need to go back a bit.
Before we met
For a long time, my favourite word at work was:
"Not now."
Not because I didn't want to help.
Because I was the only one who could do it.
Our pipeline was simple.
Build.
Deploy.
That's it.
Two stages, and only for the branches that mattered. develop went to dev. main went to prod.
It worked.
Until a developer walked up to me with this:
"Can we deploy my branch?"
And I said it.
"Not now."
But I'm not completely heartless.
So, a bit later, I added a rule.
If the branch is this one, deploy it.
Something like:
deploy:
rules:
- if: $CI_COMMIT_BRANCH == "feature/the-one-you-asked-for"
A branch name, hardcoded in the pipeline.
Done.
Next.
Then came the variables
Hardcoding one branch was fine.
Hardcoding the next one was annoying.
So I got a little smarter.
I swapped the branch name for a variable.
If DEFAULT_BRANCH equals this branch, deploy.
deploy:
rules:
- if: $CI_COMMIT_BRANCH == $DEFAULT_BRANCH
Now anyone could trigger the pipeline by hand, pass in the branch, and deploy it.
No new commit, no new rule.
And this time I was smart enough not to do it myself.
"Go to Run pipeline, set the variable to your branch, and do it yourself."
At the time, it felt like engineering.
It was also about when I started hearing the word DevEx.
And I really believed I was doing it.
Halfway, maybe.
Then it spread
It wasn't one developer, or one project.
The messages kept coming in.
But the question had changed.
It wasn't "Can you deploy my branch?" anymore.
It was:
"How can I deploy my branch?"
Progress.
Kind of.
So every time, the same little routine.
Which project?
Does that one have the variable yet?
Go to CI/CD, Run pipeline, set DEFAULT_BRANCH, wait for green.
Then the next one.
I'd stopped being the deploy button.
Now I was the manual for the deploy button.
Back to that talk
So there I was at NDC, listening to a talk about ephemeral environments.
The gist: everyone loves the idea, few teams make it stick, and it's a trade between the coordination overhead of static environments and the cost of ephemeral ones.
Coordination overhead.
That one landed.
That was me, explaining Run pipeline to one developer after another.
And one more line I'd remember later: you'll need parameters and variables everywhere, and they'll frustrate you.
I walked out thinking about my pipeline.
None of the idea was new to the world.
It was new to me.
Every merge request gets its own environment.
It comes up when the MR opens.
It goes away when the MR closes.
Nobody asks me.
Nobody waits for me.
Nobody types a branch name into a variable.
And that's when it clicked.
I'd been solving the right problem the wrong way.
I'd stopped deploying for them.
But they still needed me to tell them how.
Remember when I fell in love?
That was it.
Easier said than spun
So I tried it.
One project.
And I got lucky with the first one.
It's a monorepo. Backend and frontend, in the same place.
Nothing else to drag along.
Before I wrote a single line of YAML, I had to check something with the developer.
"Is the API URL hardcoded in a
NEXT_variable anywhere?"
Because if the frontend only knows how to talk to one specific backend, every preview frontend ends up calling the same API.
That's not a preview.
That's a costume.
The talk did warn me about variables.
Once that was sorted, the setup was pretty simple.
GitLab builds the images for the MR.
Argo CD notices the MR and spins up a preview for it.
Its own namespace, its own URL with the MR number in it, and its own fresh database on the shared dev Postgres server, with some demo data so it isn't empty.
When the MR is merged or closed, Argo deletes the preview, and a cleanup step drops its database. The empty namespace Argo leaves behind gets swept up by a small hourly job.
Open the MR. Test it. Close it. Gone.
Nobody asks me.
Honestly, I haven't fully tested it yet.
But it exists, and it's already more honest than the variable trick.
And yes, I know. I can already hear it.
"What if you have 10 MRs a day?"
"What if one MR stays open for a week? A month?"
Fair.
I don't have the answer yet.
I know there are levers.
I can cap how many MR environments run at the same time.
I can look for stale branches and clean them up.
Whether that's enough for my setup?
Still finding out.
The bit I'm actually confused about
The monorepo was the easy one.
And even that one gets its own database, not its own Postgres server.
Most of my apps aren't like that.
I haven't built this part yet, but here's the scenario I keep staring at.
An app that, to run at all, needs:
a backend, a frontend, MinIO, a database, and sometimes a CMS.
And the CMS usually brings its own backend and frontend, plus variables hardcoded for that specific app.
Now say I'm in the frontend repo, and I open an MR.
What does the preview spin up?
Just the frontend, pointed at the backend that's already running in dev?
That's fast.
But now my "isolated" preview shares a backend, a database and a bucket with everyone else. And whatever the CMS has hardcoded still points wherever it points.
Or all of it?
Backend, MinIO, a fresh database, the CMS and all its pieces, for one frontend change?
That's properly isolated.
It's also slow and expensive.
Exactly the kind of spin-up the talk warned about.
I don't know yet.
And I'd rather say that than pretend I've figured it out because a conference talk made it look clean.
What DevEx means to me
Somewhere along the way, I stopped thinking of DevEx as tooling.
For me, it's simple.
It's control.
Control given to the developer to deploy their own branch and test it before it ever reaches a customer.
A real environment where QA can poke at it.
Where a PM can click through it and say "yes, that's what I meant."
Without anyone having to ask me first.
And, honestly?
It's getting rid of the shitty daily jobs.
The ones that aren't hard, or interesting.
The ones that only exist because one person is standing between the developer and the deploy.
That person was me.
Where I am now
One project, not fully tested.
It's not done.
It's not even close.
But the direction finally feels right.
For a long time, the answer to "can you deploy my branch?" was:
"Not now."
Then it was a hardcoded rule.
Then it was a variable, and me explaining how to use it.
What I want it to be is no answer at all.
Because nobody had to ask.
Easier said than spun.
But I'm spinning it anyway.
🎧 Fell in Love — Blink-182
Originally published at najeennp.com.np/devex.
Top comments (0)