Launching Without Permission: How I Shipped a Real MVP Without Formal Sign-Off
How I shipped a real MVP without formal sign-off: validate fast, limit risk with reversible bets, and learn from real users.
Launching Without Permission: How I Shipped a Real MVP Without Formal Sign-Off
Category: startups
Everyone told me I needed a committee, a PRD, and three rounds of stakeholder reviews before shipping. I didn't have any of that. I had an idea, three weeks, and a shrinking runway. So I shipped an MVP without formal sign-off — safely, deliberately, and with real users paying within 48 hours.
This isn't a manifesto to bulldoze process. It's a practical guide on how to validate fast while keeping risk reversible and measurable. If you're a solo founder, small team, or team stuck in slow approval loops, these are patterns that actually work.
Why launch without permission?
Formal sign-off exists to reduce risk: product risk, legal risk, operational risk. But it also slows down learning. For early-stage products the biggest risk is building the wrong thing. The fastest way to de-risk that is to show something to real users and learn.
I've found that:
- Ideas die in meetings, not in production.
- Users reveal hidden assumptions much faster than spec reviews.
- You can reduce the non-product risks (legal, security, ops) to an acceptable level with deliberate, reversible controls.
So the question becomes: how do you keep the non-product risks manageable while maximizing the speed of learning? The answer is "reversible bets" and tight instrumentation.
Reversible bets: the mental model
I treat every early change as a reversible bet. A reversible bet is a change you can undo quickly if it goes sideways and that contains risk to a bounded surface area.
Examples:
- Feature flagged rollouts (toggle off instantly)
- Soft launches (invite-only, limited traffic)
- Read-only schema changes (add columns, don't transform data in-place)
- Proxying traffic through a feature service (no permanent routing changes)
The main constraints for a reversible bet:
- Fast rollback (minutes)
- Small blast radius (limited users, limited features)
- Observable (metrics and logs that show impact within minutes)
If a change can't be reversed quickly or its blast radius is large, it needs proper sign-off.
Patterns I use to launch fast (and safe)
Below are the concrete patterns and snippets I rely on.
1) Feature flags everywhere
I use feature flags for almost every new user-facing thing. For early work I avoid third-party flagging services — a simple in-app check is enough.
Node/Express example (simple Redis-backed flags):
// flag.js
const redis = require('redis').createClient();
async function isFeatureEnabled(userId, feature) {
// key: feature:users -> set of enabled userIds
return new Promise((res, rej) => {
redis.sismember(`flag:${feature}:users`, userId, (err, reply) => {
if (err) return rej(err);
res(Boolean(reply));
});
});
}
// middleware
module.exports = (feature) => async (req, res, next) => {
const userId = req.user && req.user.id;
if (!userId) return res.status(401).send('auth required');
if (await isFeatureEnabled(userId, feature)) return next();
res.status(404).send('not found');
};
This lets me enable a feature for a handful of users instantly. Rollback is removing users from that set.
If you prefer hosted tooling: LaunchDarkly, GrowthBook, or Flagsmith are solid options. For early MVPs I keep it simple.
2) Soft launches and invite lists
I never open the floodgates day one. I start with a list of 50–200 users — friends, newsletter subscribers, or people who expressed interest. That keeps load, legal, and support manageable.
Command-line workflow to add a user to a flag:
# add user 42 to early-access feature
redis-cli SADD flag:early_access:users 42
If something breaks, I remove the set and the feature disappears.
3) Safe migrations — add before change
Never do destructive migrations during an MVP launch. Use this pattern:
- Add new column/table
- Backfill if needed in a separate job
- Switch code to read/write new fields
- Drop old columns after a stabilization period
SQL example:
-- step 1
ALTER TABLE customers ADD COLUMN liked_feature BOOLEAN DEFAULT NULL;
-- step 2 (backfill in background)
UPDATE customers SET liked_feature = false WHERE liked_feature IS NULL;
-- step 3: app reads/writes liked_feature
-- step 4: DROP COLUMN after 30 days
This approach makes schema changes reversible and predictable.
4) Kill switches and circuit breakers
For any operation that touches billing, emails, or external systems, I add a kill switch. Often this is just an env var read at runtime or a "maintenance mode" flag in Redis.
Example kill switch in bash for deployments:
# deploy.sh
if [ "$(redis-cli GET maintenance_mode)" = "on" ]; then
echo "Maintenance mode enabled. Aborting."
exit 1
fi
# roll back
redis-cli SET maintenance_mode on
# roll back quickly if needed
5) Minimal legal and privacy triage
You can't ignore compliance entirely. I do a minimal legal checklist before inviting real users:
- Clear privacy text on the signup page (one paragraph)
- Opt-in for emails and billing
- No scraping of 3rd-party private data
- A GDPR-style data export/delete endpoint (even if manual behind the scenes)
A small, clear data deletion endpoint buys you a lot of trust.
6) Instrumentation and observability
If you can't measure whether the bet is winning, you can't learn. My baseline:
- Errors: Sentry (or similar) for stack traces
- Metrics: Prometheus metrics or simple events to a data warehouse
- Business events: signup, activation, upgrade, churn to Segment or a CSV log
- Logs: structured logs to a file or LogDNA/Splunk
I aim to know within 10 minutes if something breaks or conversion drops.
A simple event emitter (pseudo):
emit('signup', { userId, plan });
emit('checkout.success', { userId, amount_cents });
Hook these to a lightweight consumer that writes to a Postgres table for quick analysis.
7) Small deploys, automated rollbacks
Deploy small and often. Each deploy should be revertable with a single command. I use systemd + docker-compose for my VPSes:
git push production main
ssh prod 'cd /srv/app && docker-compose pull && docker-compose up -d'
# rollback
ssh prod 'cd /srv/app && git checkout HEAD~1 && docker-compose up -d'
On more modern infra: kubectl rollout undo deployment/my-app is your friend.
Story: How I shipped a payments MVP in 3 weeks
Quick anecdote to make this concrete.
Goal: Sell a single pro feature behind a paywall and validate willingness-to-pay.
Week 1:
- Built a minimal UI and checkout flow using Stripe Checkout (I did not implement my own PCI flow).
- Feature behind a flag; only available to invite users.
- Added a kill switch and a "payment grace" toggle to disable upgrades.
Week 2:
- Launched to 120 invites over email. Instrumented signups, trial starts, and successful charges.
- Fixed a bug exposed by real users: an edge case with phone numbers. Because the feature was flag-protected, only 8 users hit it, and it was easy to patch.
Results:
- Day 2 revenue: $320 (12% conversion of trial-to-paid in the first cohort).
- Day 7 churn: 0 for early cohort (small sample).
- Decision point at day 14: increase invites if metrics stayed healthy. They did, so I opened to 1,000 users with a gradual ramp.
If I'd waited for "formal sign-off" for the billing flow, I would have spent 6 more weeks. Instead I learned the pricing was acceptable and had real revenue before investing more.
When you shouldn't launch without permission
There are clear red lines:
- Major security changes that affect other customers
- Permanent migrations with no rollback
- Anything that violates law or contract (e.g., user data fixes that expose private data)
- Large infra changes that risk losing data
If a change touches those areas, get the necessary approvals.
Conclusion: Practical takeaways
Launching without permission isn't reckless — it's disciplined. Ship small, make reversible bets, and instrument heavily. Here are the concrete steps to follow the next time you need to move fast:
- Decide if the change is a reversible bet. If not, get sign-off.
- Gate the new feature behind a flag and an invite-only rollout.
- Use non-destructive schema changes and background backfills.
- Add kill switches for billing, email, and external integrations.
- Instrument business events (signup, activation, purchase) before you invite users.
- Start with 50–200 users, learn, then scale the invite list.
- Automate quick rollback in your deployment process.
If you're shipping alone or with a tiny team, these patterns let you get honest feedback without turning your launch into a crisis. You learn faster, take smaller risks, and keep the option to undo changes at your fingertips.
If you want, I can share the small set of scripts and migration templates I use for these launches — drop a comment or send me an email and I'll open-source the repo.