Why a Working App Is Not Yet Ready for Production
A vibe-coded app can feel complete surprisingly quickly. You describe a feature to an AI coding assistant, accept several suggested changes, run the project locally, and see the expected page appear in your browser. Forms submit. Buttons respond. Data may even be saved to a database.
That is a meaningful achievement, but it does not mean the app is ready for production.
A working app proves that a particular version of the code can complete a particular task under your current conditions. A production-ready app must continue working when it is deployed to a different environment, accessed by real users, exposed to the public internet, updated over time, and affected by failures you did not encounter during development.
The difference is not primarily about adding more features. It is about reducing uncertainty.
Before launching an app, you need to know how it handles invalid input, missing configuration, expired credentials, database failures, unexpected traffic, software updates, security threats, and deployment mistakes. You also need a way to detect problems, recover data, and restore a previous version when something goes wrong.
This article explains that gap. It does not assume that you already understand cloud infrastructure or production operations.
What “Production” Actually Means
Production is the environment where an application serves its intended users.
During development, you are usually the operator, tester, administrator, and main user. You know which buttons are unfinished. You know not to submit unusual input. You can restart the development server when it freezes. If the local database is deleted, the consequences may be minor.
Production changes those assumptions.
Real users do not know which paths you expected them to follow. They may refresh a page during a payment request, upload a larger file than expected, use an old browser, lose their internet connection, submit a form twice, or enter text in a format you never considered.
The app may also run on a different operating system, runtime version, network, domain, and database service. It may start without the local files, environment variables, or cached data that existed on your computer.
Production readiness therefore means more than “the application has been deployed.” It means you have prepared the application to operate in conditions that are less predictable than your local development environment.
Google’s Site Reliability Engineering material describes production readiness reviews as a way to identify a service’s reliability requirements and determine whether its architecture, monitoring, operational procedures, and failure handling are adequate for real use.
A solo developer does not need to reproduce a large company’s review process. However, the underlying question is still useful:
What must be true before other people can reasonably depend on this application?
A Working App Proves Less Than You Think
Imagine that you built a small appointment-booking app with an AI coding assistant.
On your laptop, you can:
- Open the home page.
- Select an available time.
- Enter a name and email address.
- Save the appointment.
- View it in an admin dashboard.
This confirms that the main workflow can succeed. It does not confirm that the application is secure, reliable, recoverable, or maintainable.
You may not yet know what happens when:
- Two people choose the same appointment at nearly the same time.
- The database becomes temporarily unavailable.
- A user submits an invalid or extremely long email address.
- The admin page is opened by someone who is not an administrator.
- The API key is missing after deployment.
- A database migration changes an existing table.
- The deployment completes but one important route returns an error.
- An AI-generated dependency contains a known vulnerability.
- A new release breaks appointments created by the previous version.
These are not unusual edge cases that only matter to large businesses. They are ordinary production conditions.
A working demo is evidence that the application can succeed. Production readiness requires evidence that it can also fail safely.
The Main Gaps Between Development and Production
1. Your local environment may be hiding missing configuration
A local app often depends on configuration that is not obvious from the source code.
Examples include:
- Environment variables loaded from a
.envfile - A locally installed runtime or command-line tool
- A specific Node.js, Python, or database version
- Files stored on your computer
- A development-only proxy
- Browser data from an earlier test
- A database table you created manually
- An API credential saved by another tool
When the application is deployed, those assumptions may disappear.
A production-ready project should make its requirements explicit. Another environment should be able to install, configure, build, and start the application without depending on undocumented steps from your laptop.
The Twelve-Factor App methodology recommends keeping deployment-specific configuration outside the codebase so that configuration can change between deployments without modifying the application code. It also warns that configuration files can be accidentally committed or scattered across a project.
For a beginner, the practical lesson is:
- Document required variables.
- Provide safe example values where appropriate.
- Pin important runtime versions.
- Define repeatable build and start commands.
- Test the project in a clean environment.
Do not assume that a successful local run proves the deployment platform can reproduce your setup.
2. Development settings may be unsafe for public use
Development tools prioritize speed and visibility. Production settings should prioritize controlled behavior and limited exposure.
A development server may display detailed error pages containing:
- Source-code paths
- Database queries
- Internal service names
- Configuration details
- Stack traces
- Parts of incoming requests
Those details can help you debug a problem, but they should not automatically be shown to public users.
Development configurations may also allow broad cross-origin requests, weak test passwords, unprotected administrative routes, or debugging extensions. OWASP’s Web Security Testing Guide recommends checking that debugging code and unnecessary extensions are not left enabled in production. It also recommends reviewing whether security-relevant events are recorded without causing additional information exposure.
Before launch, verify that the app:
- Uses production mode.
- Returns user-safe error messages.
- Keeps detailed errors in protected logs.
- Disables test accounts and debugging tools.
- Restricts administrative functionality.
- Allows requests only from intended origins where relevant.
Changing a variable from development to production is not enough by itself. You still need to examine how your framework behaves in each mode.
3. Successful requests do not prove that authorization works
Authentication answers: “Who is this user?”
Authorization answers: “What is this user allowed to do?”
An AI-generated app may implement a login page while failing to protect the underlying server route. Hiding an admin button in the interface does not prevent someone from sending a direct request to the admin API.
Production authorization must be enforced on the server.
For the appointment app, that means a normal user should not be able to:
- Read every customer’s appointments.
- Change another user’s booking.
- Access the admin dashboard data.
- Delete records by editing a request URL.
- Assign themselves an administrative role.
Server-side validation matters for the same reason. Browser controls improve the user experience, but a user or automated client can bypass them and send requests directly.
OWASP’s Application Security Verification Standard provides a structured set of requirements for verifying application security controls rather than assuming that the presence of a feature makes it secure.
You do not need to implement every enterprise-level control before launching a small project. You do need to identify which data and actions require protection and verify those protections independently of the visible interface.
4. Your secrets may be inside the code or browser bundle
Vibe coding increases the risk of credential mistakes because an AI assistant may generate configuration quickly without understanding how your deployment platform exposes variables.
An API key should not be placed directly in source code. It should also not be placed in client-side configuration merely because the variable is called an environment variable.
In many frontend build systems, variables intended for browser use are included in the generated JavaScript. Anyone who loads the page may be able to inspect them.
A secret must remain on a trusted server. The browser should call your server, and your server should call the protected third-party service when appropriate.
Before deployment:
- Search the repository for API keys, passwords, tokens, and private connection strings.
- Remove secrets from source-controlled files.
- Add sensitive local files to
.gitignore. - Store production secrets in the deployment platform’s secret or environment-variable system.
- Give credentials only the permissions they require.
- Rotate any credential that may already have been committed.
Deleting a secret from the latest file does not necessarily remove it from Git history. Treat an exposed credential as compromised and replace it.
GitHub’s push protection is designed to detect supported secrets and block them before they are pushed to a repository, although developers should not treat automated detection as a replacement for reviewing code and configuration.
5. A production database is not a larger development database
Development data is usually disposable. Production data may represent users, orders, messages, bookings, or other records that people expect you to protect.
This changes how you handle database operations.
During development, you might resolve a schema problem by deleting the database and recreating it. In production, that could permanently destroy user information.
A production database requires decisions about:
- Access control
- Connection security
- Schema migrations
- Backups
- Restore procedures
- Data retention
- Capacity
- Failure recovery
- Privacy
- Rollback compatibility
You should also consider concurrency. A workflow that succeeds when one person uses the app may fail when multiple requests modify the same record.
In the appointment example, checking whether a time is available and then creating a booking as two unrelated operations can allow double booking. The production implementation may need a database constraint or transaction so that the rule is enforced even when requests arrive nearly simultaneously.
The important principle is that application code should not be the only place protecting critical data rules.
6. Manual testing covers only the paths you remember
When you build an app, you naturally test the feature you just implemented. You enter expected data, follow the intended flow, and confirm the visible result.
Production testing must go further.
At minimum, test:
- The main successful workflow
- Empty and invalid input
- Permission boundaries
- Failed network requests
- Missing environment variables
- Duplicate submissions
- Refreshing during a multi-step operation
- Direct access to protected URLs
- Mobile layouts
- A clean production build
- Database migration behavior
- Error pages and recovery paths
Automated tests are valuable because they repeat important checks after every change. They are not proof that the application has no defects. A test suite only checks the situations represented by its tests.
AI coding tools can also generate tests that confirm their own assumptions rather than the intended business behavior. Review whether each test would fail if the feature were genuinely broken.
A useful question is not “Do tests pass?” but:
What important behavior does each test demonstrate, and what remains untested?
7. You cannot fix a problem you cannot see
On your computer, an error appears in the terminal. In production, the error may happen on a remote server while you are offline.
Without logging and monitoring, your first indication of a failure may be a user complaint.
Production visibility usually includes:
- Application logs
- Error reports
- Request status and latency
- Deployment history
- Resource usage
- Database health
- Availability checks
- Alerts for important failures
Logs should provide enough context to investigate a problem, but they should not contain passwords, access tokens, payment information, or unnecessary personal data.
The Twelve-Factor App approach recommends treating logs as event streams that can be collected and analyzed by the surrounding execution environment.
Google’s production-readiness guidance similarly asks whether a service reports errors to centralized logging systems so that incidents can be investigated from a coherent set of information.
For a first app, you do not need an elaborate monitoring center. You should at least be able to answer:
- Is the app currently reachable?
- Are requests failing?
- Which release introduced the problem?
- What error occurred?
- Which part of the system is affected?
- Did the database or an external API contribute to the failure?
8. Deployment success does not prove application success
A platform may report that a deployment succeeded because it installed dependencies, completed the build, and started a process.
That does not prove every feature works.
The deployed app may still have:
- A missing environment variable
- An incorrect callback URL
- A failed database migration
- Broken image or file paths
- An API blocked by cross-origin rules
- An authentication cookie configured for localhost
- A route that works only through the development server
- A dependency that behaves differently in production mode
After deployment, run a small set of smoke tests. A smoke test is a fast check of the most important functions.
For the appointment app, that might include:
- Open the public home page.
- Create a test appointment.
- Confirm that it appears in the admin view.
- Verify that an unauthorized user cannot open the admin data.
- Delete or mark the test record appropriately.
- Check the application logs for unexpected errors.
Deployment is the start of production verification, not the end.
9. Updates create a new category of risk
A local app only needs to work in its current state. A production app must survive change.
A new version may alter:
- Database schemas
- API request formats
- Session behavior
- Environment variables
- Build commands
- Dependencies
- Cached assets
- Background jobs
Some changes are not backward-compatible. For example, a new release may expect a database column that has not yet been created. A migration may remove a field that the previous release still needs, making a quick rollback impossible.
Safe updates require version control, review, validation, and a rollback plan.
Before each production change, know:
- What is changing?
- How will you verify it?
- What data could be affected?
- Can the previous version still run?
- How will you restore service if validation fails?
A hosting platform’s rollback button can restore earlier application code, but it may not reverse an incompatible database migration or recover deleted data.
10. Failures require prepared responses
Production systems eventually encounter failures. The goal is not to pretend that failure can be eliminated. The goal is to limit its impact and recover predictably.
You should prepare for situations such as:
- A bad deployment
- A failed migration
- An unavailable external API
- An expired credential
- Accidental data deletion
- Unexpected traffic
- A compromised account
- A platform outage
Preparation may include:
- A known-good release
- Automated database backups
- A tested restoration procedure
- Deployment logs
- A maintenance message
- Credential-rotation steps
- Contact details for important service providers
- Written rollback instructions
A backup is not fully trustworthy until you know how to restore it. A rollback strategy is not complete until you know which application, configuration, and database changes it reverses.
How AI-Assisted Development Changes Production Risk
AI coding assistants can help beginners build faster, but speed can hide missing understanding.
An assistant may:
- Invent an environment-variable name.
- Use an outdated API.
- add an unnecessary dependency.
- Put server credentials in browser code.
- Modify unrelated files.
- Create incomplete authorization.
- Catch errors without reporting them.
- Claim a task is complete because the build passed.
- Generate a migration that discards existing data.
- Create tests that do not verify the real requirement.
These mistakes are not reasons to avoid vibe coding. They are reasons to use a controlled workflow.
For production-related changes:
- Describe the goal and constraints clearly.
- Ask the assistant to identify affected files before editing.
- Keep each change focused.
- Review the Git diff.
- Check new dependencies and configuration.
- Run relevant tests.
- Build the app in production mode.
- Verify the result manually.
- Commit a known-good state before risky changes.
- Preserve a rollback path.
Never rely on an assistant’s statement that a deployment, test, security check, or migration succeeded. Verify the actual command output, platform status, logs, and application behavior.
A Practical Definition of “Ready Enough”
Production readiness is not a single universal standard. A personal portfolio site and a healthcare system do not have the same risk profile.
The amount of preparation should match:
- The sensitivity of the data
- The consequences of downtime
- The number of users
- The financial impact of errors
- Legal or contractual obligations
- The difficulty of recovering lost data
- The permissions granted to the application
A small read-only project with no user accounts may require relatively limited preparation. An app that stores personal information, processes payments, controls paid resources, or makes important decisions requires much stronger controls and professional review.
For a beginner project, “ready enough for an initial launch” might mean:
- The production build completes from a clean checkout.
- Required configuration is documented.
- Secrets are kept out of the repository and frontend bundle.
- Authentication and authorization are checked on the server.
- Inputs are validated on the server.
- Critical workflows have repeatable tests.
- The production database has backups.
- A restore procedure is documented and tested safely.
- Errors are recorded without exposing sensitive data.
- Basic availability and error monitoring are enabled.
- Important post-deployment checks are documented.
- A previous release can be restored.
- Known limitations are clearly recorded.
This is not a guarantee that nothing will fail. It is evidence that you have considered predictable risks and created ways to detect and respond to problems.
Production Readiness Starts Before Deployment
The biggest mistake is treating production preparation as the final button you press after development.
Production readiness affects architecture, configuration, database design, error handling, security, testing, and update strategy. Waiting until launch day may reveal that important assumptions are built deeply into the application.
You do not need to solve every operational problem at once. Work in layers:
- Make the application reproducible.
- Separate configuration from code.
- protect secrets and user data.
- verify access controls.
- prepare the production database.
- test important workflows and failure paths.
- add logs and monitoring.
- deploy to a controlled environment.
- run post-deployment checks.
- document rollback and recovery procedures.
This series will cover those steps individually, beginning with how to choose an appropriate deployment platform.
The key lesson is straightforward:
A working app demonstrates a feature. A production-ready app demonstrates that the feature can be operated responsibly.
Beginner Production-Readiness Checklist
Before calling your app ready for users, confirm:
- The project builds from a clean checkout.
- Runtime and dependency requirements are documented.
- Development and production settings are separated.
- No private credentials are stored in the repository.
- No server-only secrets appear in browser code.
- Authentication and authorization are enforced server-side.
- User input is validated server-side.
- Production errors do not expose internal details.
- Important workflows have been tested.
- Failure and invalid-input paths have been tested.
- Database changes use reviewed migrations.
- Production data is backed up.
- A restoration procedure exists.
- Logs avoid secrets and unnecessary personal data.
- Availability and important errors can be monitored.
- Post-deployment smoke tests are documented.
- A failed application release can be rolled back.
- Risky database changes have separate recovery plans.
- Known limitations are recorded before launch.
