I Built the MVP. Then I Realized Shipping Was a Different Skill.
A few days ago, I wrote about something I had learned the hard way:
Building the MVP first and writing the README later made me realize how much I had assumed.
I thought that was mostly a documentation problem.
It wasn't.
The deeper problem was that building something and shipping something are two different skills.
The MVP was working
I recently built Security Lens, a Spring Boot-based privacy risk analyzer for images and documents.
The basic flow was working:
Image Upload
↓
OCR
↓
Personal Information Detection
↓
EXIF Metadata Analysis
↓
Risk Scoring
↓
LLM-assisted Analysis
↓
Risk Explanation
It could detect things such as:
- phone numbers
- email addresses
- EXIF GPS information
- capture timestamps
- device metadata
and turn the results into a simple privacy risk score.
At that point, I had something that worked.
I thought I was almost done.
I wasn't.
"It works" was only the beginning
Once I tried to actually ship the project, a different set of questions appeared.
Not:
Does this method work?
But:
Which exact version is deployed?
What happens if an environment variable is missing?
Did I actually verify the production configuration?
What if the database or external integration behaves differently from localhost?
What evidence do I have that the deployed application is healthy?
Can I roll back?
Those questions were not really about writing more code.
They were about operating the thing I had already written.
Deployment exposed assumptions
Localhost is forgiving.
Your machine already has:
- your environment variables
- your tools
- your configuration
- your ports
- your dependencies
- your development habits
Production does not care about any of that.
It only gets what you actually configured.
While working through deployment, I ran into issues around ports, environment setup, AI integration, and the difference between an implementation that works locally and one that can actually run as a product.
That changed how I looked at "done."
AI made this even more interesting
I use AI tools heavily while building.
They are extremely useful.
But I also noticed a dangerous pattern.
It is very easy to ask:
"Is this production-ready?"
and get an answer that sounds convincing.
The problem is that confidence is not evidence.
So I started using a different rule:
If the evidence is missing, the result is NOT VERIFIED.
Instead of asking AI to make the release decision for me, I ask it to help inspect:
- configuration
- logs
- build output
- deployment settings
- security assumptions
- missing evidence
The AI can be a reviewer.
It should not silently become the owner of the release decision.
That became a checklist
While repeatedly asking myself the same deployment questions, I started writing them down.
Eventually, those notes became a small public project:
Spring Boot Release Checklist
It focuses on things like:
- clean builds
- expected tests
- configuration and secrets
- database connectivity
- external integrations
- production smoke tests
- rollback points
- evidence-first AI review
The main idea is simple:
A successful deployment is not the same as a verified release.
Then I noticed something else
The checklist helped me catch blockers.
But I still wanted a better way to answer:
What did I actually verify?
Where is the evidence?
What still remains uncertain?
Should I ship this version?
That eventually became a more structured release workflow with interactive checks, evidence fields, AI review prompts, and ship / no-ship decisions.
I ended up turning it into a 58-page deployment runbook.
That was another new experience for me.
For the first time, I was not only building software.
I was taking something I had learned while building software and turning it into something another developer could actually use.
Shipping forced me to learn things coding alone did not
The interesting part was not setting up a product page.
It was everything around it.
I had to think about:
- what the product actually solves
- how to explain it in one sentence
- what should remain free
- what someone would reasonably pay for
- how a buyer receives the files
- how the download flow works
- what happens after payment
- how the public GitHub repository connects to the full version
None of these problems required a complicated algorithm.
But they still required engineering decisions.
My definition of "done" is changing
Before:
Feature works
→ done
Now:
Feature works
→ build succeeds
→ configuration is verified
→ deploy
→ production smoke test
→ evidence recorded
→ rollback understood
→ documentation updated
→ then maybe done
It is slower.
But it feels much closer to building something real.
One more thing I learned
I used to think "shipping" was mostly the final step after development.
Now I think it changes how you develop from the beginning.
When you know you will actually deploy something, you think differently about:
- configuration
- secrets
- observability
- failure cases
- reproducibility
- documentation
- users
The project stops being just code.
It becomes a system someone else has to trust.
What's next
I am continuing to improve Security Lens and experimenting with the same workflow on other small products.
The Security Lens source code remains private, but I created a public technical case study here:
Security Lens — Technical Case Study
And the lightweight Spring Boot release workflow is available here:
Spring Boot Release Checklist
For me, the biggest lesson so far is simple:
Coding makes the product possible. Shipping makes it real.
Still learning.
Still shipping.