AI & Engineering
From AI Prototype to Production: What Still Needs Work
A practical walkthrough of permissions, double bookings, retries, monitoring, and recovery using a hypothetical AI-built booking app.
Rommel Clarino 7 min read
At a glance
A working demo is a starting point. Before releasing a booking app, define what confirmation means, enforce permissions and capacity, make retries safe, and rehearse recovery. AI can help implement each step; verify the behavior before relying on it.
A working demo is the beginning
An AI coding tool helps you build a booking app. The calendar looks good, the form submits, and a confirmation appears. You can demonstrate the whole flow in a minute.
Then two people try to reserve the same appointment. Someone changes a booking ID in a request. An email provider times out after the reservation has already been saved.
The prototype has answered an important question: can this experience work? Production asks another: can people depend on it when inputs, timing, and services stop cooperating?
Let’s follow one hypothetical app from its first successful booking to a release we can explain and operate. The AI helps write the app; the app itself does not need an AI feature.

1. Define what “booked” actually means
In a demo, a success message can make the task feel complete. In production, that message needs a precise meaning.
For our app, a confirmed booking means the server has accepted the request, reserved the slot exclusively, and saved a record belonging to the signed-in customer. Email delivery is a separate status. A failed email must not turn a valid reservation into a failed booking.
Write those rules before asking AI to harden the code. “Make this production-ready” leaves too much room for invented assumptions. “Prevent two confirmed reservations for the same slot” describes behavior you can inspect.

2. Put permissions where requests are handled
A login page establishes who someone is. Each protected operation still needs to decide what that person can do. OWASP recommends denying access by default and validating permissions on every request.
Suppose Alice owns booking A and Bob owns booking B. Alice can cancel A. If she submits B’s identifier, the server should refuse the action before changing any record. Hiding Bob’s booking in Alice’s interface does not enforce this rule.
Use the verified session to establish the customer identity. Validate the request on the server, check ownership, and apply the cancellation policy there. Keep service credentials out of browser code. Give administrative actions explicit permissions.
The useful verification is concrete: two customers, two reservations, and an attempted cancellation across that boundary. The unauthorized request must leave the reservation untouched.
3. Protect the booking rule when requests overlap
A prototype might read “slot available” and then insert a reservation. Two requests can both read the same available slot before either writes its booking.
For this example, appointments are fixed slots with a capacity of one. Enforce that rule with an atomic database operation and an appropriate uniqueness constraint for active reservations. Define how cancellation releases a slot. Flexible time ranges need a different overlap policy; a unique start time alone would be insufficient.
The interface should handle losing that race gracefully: “That appointment was just booked. Choose another time.” Availability displayed a moment ago is useful guidance, but the write decides whether the reservation succeeds.
AI can propose the transaction and constraint. Review whether they enforce your actual capacity and cancellation rules, then exercise two competing requests against the implementation.
4. Treat a timeout as an uncertain outcome
The server saves a reservation, but the response never reaches the browser. The customer clicks again. Without duplicate prevention, one intended action may create two records.
For our proposed design, the client creates a key for one booking attempt and reuses it on retries. The server scopes that key to the customer and operation, stores the result durably, and prevents competing requests from processing it twice. A reused key with different booking details should be rejected. Define its retention window and the behavior of requests still in progress.
An API provider may offer its own mechanism. Stripe, for example, documents idempotency keys for retrying requests, with specific rules for storing and reusing results. That provider feature does not automatically deduplicate your application’s booking records.
Email has another failure boundary. One option is to save the booking and an email job in the same database transaction, then let a worker deliver it with bounded retries. If delivery remains unsuccessful, preserve the reservation, show its notification status, and give someone a way to investigate. Duplicate email handling depends on the delivery provider’s guarantees.

5. Make failures visible and actionable
“Something went wrong” gives both the customer and the developer very little to work with.
The customer needs an accurate next step: choose a different slot, sign in again, or check an existing reservation before trying another booking. Never show a definitive failure when the server may already have completed the action.
The operator needs evidence. Record a request identifier, booking identifier when available, processing stage, and outcome. Exclude credentials and unnecessary personal information. Combine structured logs with measures such as booking failures and notification backlog; use traces when following a request across services would help. OpenTelemetry explains how logs, metrics, and traces contribute to observing a system.
An alert also needs an owner and a response. “Notification jobs are accumulating” is useful when someone knows how to inspect the queue, restore delivery, and confirm that pending work resumed.
6. Rehearse release and recovery
Deploying the interface is only part of releasing the system. The application, database schema, configuration, and background jobs need to agree.
Run the important booking scenarios in staging. Check production configuration without exposing secrets. Apply schema changes in a way that remains compatible with the versions running during deployment. Rehearse restoring a backup rather than assuming that creating one proves recovery works.
Start with a limited audience where practical. Watch whether people can complete bookings and whether background work stays healthy. Decide in advance who can pause new bookings and how an application rollback interacts with database changes. Rolling back code does not undo reservations, emails, or incompatible migrations.

What I would verify before opening this app
These checks are a starting point for this example. Your app’s data, users, and integrations determine what else the release needs.
| Scenario | Required outcome |
|---|---|
| Alice submits Bob’s booking ID | No unauthorized read or change |
| Two customers reserve one fixed slot | At most one confirmed reservation |
| The response disappears after saving | Retry resolves to the same booking |
| A key is reused with different details | Request is rejected without a new booking |
| The email provider is unavailable | Booking remains saved; notification work is recoverable |
| A deployment introduces a failure | An owner can pause the affected operation and follow a rehearsed recovery path |
Give AI smaller, verifiable jobs
Ask AI to trace the booking request from session validation to the database write. Ask it to identify the window where two requests can both succeed. Ask it to draft customer messages for the failure states you have defined. Review each change against the behavior you need and run the relevant checks after implementation.
A working prototype is valuable: it makes the idea tangible and lets you learn quickly. The next investment is to make its promises dependable. For this booking app, I would start with permissions, exclusive slot reservation, and duplicate prevention. Those decisions protect the central promise before adding more features: when the customer sees “confirmed,” the reservation exists and belongs to them.