The boxes are already on the board. A browser sends photos to an upload API, the API writes to object storage and a metadata database, a queue feeds a thumbnail worker, and a CDN serves the result. It looks complete until you follow the arrows. The API returns "photo ready" before the worker has run. A line from object storage to the public CDN cuts across the claim that photos are private. The worker has a retry arrow but nowhere to put a job that keeps failing.
This is a fictional photo sharing service for an interview exercise. Assume signed-in users upload photos, only the owner may view them, and the gallery uses a thumbnail generated after upload. The drawing is a request-flow sketch, not a complete production design. The final review is about whether this sketch tells one consistent story. It is different work from choosing the first boxes.
Follow the response before adding another component
Start at the browser's upload request and say what each arrow means. In the initial drawing, the API accepts the file, stores the original, writes a photo record, places a thumbnail job on the queue, and returns 200 photo ready. But the gallery needs a thumbnail that does not yet exist. The response and the asynchronous path disagree about what "ready" means.
Change the response label to "upload accepted" and give the record a processing state. In this example, the API sends that response only after it has stored the original, written the pending record, and received confirmation that it queued the job. The browser can show processing while the worker reads the private original, creates the thumbnail, stores it, and changes the record to ready. A gallery read returns the state and retrieves the thumbnail through an authorized path only when one is available. If the product instead requires a thumbnail in the first response, the work has to finish before that response; that is a different latency and failure tradeoff. Do not draw an asynchronous worker and promise a synchronous finished result.
The edit also raises a smaller question. What if the file reaches object storage but the metadata write or queue submission fails? The API would withhold the accepted response, yet the stored object might remain. In a short review, label this as an incomplete handoff and say how you would investigate it, perhaps with an upload record that can be reconciled with stored objects. The exact transaction and recovery mechanism need more design. A diagram alone cannot guarantee that the storage write, database write, and queue message always agree.
Trace one failure all the way back to the user
Now follow the thumbnail job when processing fails. A retry arrow to the same worker says very little. Is the failure temporary? Can the same job run twice? When does the system stop trying, and what does the owner see then? A worker that never produces a thumbnail must not leave the photo in processing forever without an explanation.
For this example, let the queue retry a bounded number of times. Make the thumbnail operation safe to repeat for the same photo and version, since the worker may process a job again after an uncertain result. After the retry policy is exhausted, move the job to a place for investigation and mark the photo failed in the metadata store. The gallery then shows a failed processing state rather than a broken image. Those are design decisions for this fictional service, not properties supplied automatically by drawing a queue. A real implementation would need to define how the failed-job route and the metadata update stay consistent.
You do not need to map every storage outage on the board. Follow one representative failure from the worker to the user-facing state. If the failure ends at a monitoring box, the explanation is still incomplete: an alert may help an operator, but it does not tell the owner what happened to the upload. An operator signal can be noted beside the failed-job path without turning this view into an operations dashboard.
Check who can cross each boundary
The original storage-to-CDN line is the most serious contradiction. If the CDN can fetch and serve originals from a public location, a browser may bypass the owner check in the API. Writing "auth" inside the API box does not protect a second path around it. The review should identify which component authorizes a view request and which stored objects that decision covers.
For this sketch, keep originals and thumbnails private. The browser asks a read API for a photo; the API checks that the signed-in user owns it and that the requested representation is ready. The API then reads the private object and returns it. Remove the public CDN path from this view. Sending the image bytes through the API costs server bandwidth and may become a bottleneck. A later version could use a protected serving path, but its access rule must be explicit: a transferable signed URL, for example, lets anyone holding it read the object until it expires. That is a narrower privacy promise than checking ownership on every read. If the requirement changes to public sharing, draw that as a separate policy.
Upload is another trust boundary. The client can claim a file is an image and supply a filename, but the service has to decide what it will accept. The OWASP File Upload Cheat Sheet recommends authorization, size limits, allowed file types, and checking content rather than trusting the client-supplied content type. In this sketch, put "authenticate, authorize, limit and validate" on the upload API before it treats the file as a photo. If the browser uploads directly to object storage in a later revision, move that review to the credential-issuing and post-upload processing path; removing the API from the byte path does not remove the trust decision.
Spend the remaining time on contradictions
The revised drawing can stay small:
Upload: browser -> Upload API -> private original store
|-> photo metadata: processing
|-> queue -> thumbnail worker
|-> reads private original
|-> writes private thumbnail
|-> photo metadata: ready or failed
|-> failed-job record if retries end
Read: browser -> Read API -> metadata: owner and state check
-> private original or thumbnail -> browser
The arrows still need spoken explanation. Upload acceptance means the original, pending record, and queue request were acknowledged, not that a thumbnail exists. The worker changes the processing state after it has made the thumbnail. A repeated or failed job follows an explicit policy. The read API checks the owner before retrieving either stored representation.
With little time left, fix the statements that can make the whole story false: the premature "ready" response, the failure with no terminal state, and the path that bypasses authorization. Then name the most consequential unresolved assumption. Here it is the consistency of the storage, metadata, and queue handoff. Scaling numbers, image variants, and CDN tuning can wait until the interviewer asks for them. Adding those boxes now would make the sketch denser while its existing promises remain untested.
A final pass can be brief: pick one successful upload, one failed processing attempt, and one unauthorized read. For each, point to the response the browser gets and the component that makes the decision. If you must invent an invisible step while speaking, mark it on the diagram or state it as an open design choice. You can practice that revision in Lycana by speaking or typing the missing component or relationship, then explaining the changed path aloud. The tool will not decide whether the privacy rule or failure policy is sound. This is practitioner guidance for making an explanation coherent, not a claim about interview scores. The Software Engineering Institute's architecture documentation review note likewise frames review around whether a document gives its reader enough information for their task; it does not establish an interview outcome.


