There is a category of bug that is trivial to fix, obvious in retrospect, and costs a user something they cannot get back. This is ours.

What happened

Someone opened an entry they had written a week earlier, read it, and closed the app. When they came back, it was empty.

The editor worked like this. It set up its state — an empty document — then asked the database for the entry and populated the state when the result arrived. Autosave watched the state and persisted changes after a short debounce.

Between construction and the database returning, the state was legitimately empty. On a fast device with a warm database, that window was a few milliseconds and nothing happened. Under the right conditions — a cold start, a large database, a device under load, a slow read — the window was long enough for the autosave debounce to elapse. Autosave saw an empty document, faithfully persisted an empty document, and the entry was gone before it had finished loading.

Autosave was doing precisely what it was told. It was told the wrong thing, because nothing distinguished "this document is empty" from "this document has not loaded yet."

That is the same distinction that shows up everywhere once you start looking: empty is a value, unknown is not, and conflating them is how you get software that confidently asserts something false.

The fixes, in order of importance

Autosave does not run before the document has loaded. The editor state is explicitly a loading state until the read completes, and the autosave path ignores anything that is not a loaded document. One condition. This is the fix.

Autosave never writes an empty document over a non-empty one without an explicit action. A belt for the braces. If the content goes from something to nothing, that is a deletion, and deletion is a thing the user does deliberately, not a thing that falls out of a save.

Saves are versioned. Each entry keeps its recent previous versions, so a bad write is recoverable rather than terminal. This is not a full history feature — it is a small ring buffer, invisible unless something goes wrong. The cost is negligible for text and it converts an unrecoverable failure into an annoyance.

Deletes are recoverable for a window. Deleting an entry moves it out of the list and keeps it for a period before it is actually removed. There is very little in a diary app that benefits from being irreversible.

Autosave after the fix

Since it is now a feature we trust rather than one we are nervous about, the rest of the design is worth describing.

The editor debounces: it saves after a short pause in typing, rather than on every keystroke. Writing continuously produces no writes at all until you stop, which is the correct behaviour — an entry being composed does not need a database write per character, and a stream of writes is how you make an editor feel sluggish on an older device.

It also saves unconditionally when the app goes to the background. This is the moment that actually matters. A phone that dies, an app the system reclaims, a call that arrives — all of them go through a lifecycle callback first, and saving there means the pause-based debounce is a nicety rather than the only line of defence.

And if the process is killed with unsaved changes anyway, the draft is recovered on next open. Recovery is presented explicitly — the app says there is an unsaved draft from a particular time and asks — rather than silently restoring text that may or may not be what you wanted.

Why this matters more for a diary than for most apps

A diary entry is not reproducible. If a note app loses a shopping list, you rewrite the shopping list. If a diary loses what you wrote about a Tuesday, the Tuesday is not available for a second attempt.

This shapes the defaults. Everything in the app leans towards keeping too much rather than too little: versions, a delete window, explicit draft recovery. The storage cost of text is essentially zero, and the cost of the alternative is not measurable in bytes.

It also means we are conservative about features that transform existing entries. Anything that rewrites what you already wrote — a formatting change, a bulk edit, a migration — gets more caution than the feature itself seems to warrant.

The five-minute routine

The software's job is to never lose anything and never be slow to open. Everything else is habit, and the habit that works is much smaller than most people attempt.

Find the day's anchor first. One thing that gave the day its shape: a place, a person, a meal, a piece of work that finished, a conversation that did not go well, the weather changing. The blank screen is hard; a blank screen with an anchor already chosen is not.

Write the first sentence plainly. "Worked from home and finally finished the report." "Met a friend near the station." "Tired, but walked after dinner." A plain first sentence removes the pressure to be interesting, and entries usually grow on their own once they have started.

One photo, chosen as a cue rather than a picture. A receipt, a street corner, your desk, a ticket, the sky. It does not need to be good. It needs to bring the day back. Ten similar photos are worse than one — the entry becomes a gallery and stops being a memory.

Add place only when it means something. A café you worked in, a park you walked through, a city you were visiting. Not every entry needs coordinates, and a diary that logs your movements is a different and less pleasant object than one that records where things happened.

One line of context. "First rainy day after a hot week." "Nervous before the meeting." Small, and it is what makes an entry vivid on re-reading rather than flat.

Stop. Five minutes. The entry does not have to be complete or good.

The failure mode is quitting, not writing badly

Almost everyone who abandons a journaling habit does it the same way: they miss a day, then feel the gap needs filling, then face the accumulated weight of three missed days, and stop.

The design response is that ONEDiary does not have streaks and does not mark missed days. Nothing tells you that you skipped Tuesday. An empty day is an empty day, not a failure state, and you can write about today without addressing it.

Ordinary days are also worth recording, and the app deliberately does not push you towards the significant ones. "Nothing much happened, it rained, I read for a while" is a perfectly good entry and in five years it is a better one than most of the important days, because it is the texture of a period rather than a headline.

Templates, used as a door and not a cage

If you do not know what to write, a structure helps: what happened, how it felt, what to remember, what tomorrow needs. One sentence each.

The trap is using the same structure every day until it becomes a form to complete. Change the questions when they go stale. Some days want gratitude, some want to work through a problem, some want a plain record of facts, and some want a place to write that nothing happened. A diary app that only supports the meaningful days is not much use, because most days are not those.