Skip to content
EL
Contents

Plain files, CSV, JSON and the cost of DIY storage

How programs store records in files

ConceptFoundation4 min read#fundamentals#storage

The idea in 30 seconds

A file is just a sequence of bytes; a format like CSV or JSON is an agreement about what those bytes mean. Because records in these formats have no fixed size or position, finding one means reading and parsing the whole file, and changing one usually means rewriting all of it. That cost grows with every record you add.

Helps to know first: What data is, and why we need a database

On this page

A file is bytes; a format gives them meaning

To the operating system, a file is nothing but a numbered sequence of bytes. It does not know about users or orders. A format is an agreement between the programs that write and read the file about what those bytes mean.

FormatOne record looks likeGood atWeak at
CSV42,Asha,asha@example.comTables, spreadsheets, exportsNesting, types: everything is text
JSON{"id": 42, "name": "Asha"} inside one big arrayNested data, readable by peopleThe whole file is one value, so it is read and written as a whole
JSON LinesOne JSON object per lineAppending records one at a timeChanging or removing a record in the middle
Binary formatsBytes laid out for machines (Parquet, Protocol Buffers)Size and speedYou need a tool to read them

All four share one property that matters a lot: records have no fixed size or position. “Asha” takes fewer bytes than “Venkataraman”, so record 42 could start anywhere. There is no way to jump straight to it.

Finding one record means reading everything

If you cannot jump to a record, you have to read from the start until you find it. For a JSON file it is worse: the whole file is one array, so the program reads and parses every record into memory before it can look at any of them.

That cost grows in a straight line with the size of the file. Double the users, double the time to find one.

PredictOne update, one million users

A JSON file holds one million users, about 74 MB. You change one user’s name: load the file, change one field, save the file. Roughly how long does that take on a laptop?

Changing a record means rewriting the file

Opening a file for writing normally truncates it: the old contents are thrown away and the new ones written from the beginning. To change one record in a JSON file, a program reads everything, changes the record in memory, and writes everything back.

There are two cheaper alternatives, and both lead somewhere interesting:

  • Append instead of rewrite. With JSON Lines, adding a record is one write at the end of the file. Opening a file in append mode makes every write land at the end. But to change record 42 you either rewrite the file or append a new version of record 42 and let readers take the last one. Then the file keeps growing with stale versions, and something has to clean them up from time to time. That is the core idea behind log-structured storage engines.
  • Give every record a fixed size and position. If each record takes exactly 100 bytes, record 42 starts at byte 4,200, and you can read or overwrite it without touching anything else. Databases build on this idea: they store data in fixed-size pages and keep indexes that say which page holds which key.

Either way, you have started building a database.

Check yourself

  1. Why can’t a program jump straight to record 42 in a CSV or JSON file?

    Show answer

    Records have no fixed size, so their byte positions depend on every record before them. Without an index of positions, the only way to find one is to read from the start.

  2. Why does changing one user’s name in a large JSON file take seconds?

    Show answer

    JSON stores the whole collection as one value. To change any part of it, the program parses everything into memory and writes the entire file back out.

  3. JSON Lines lets you append a record with one write. What problem does that leave for updates and deletes?

    Show answer

    You must either rewrite the file, or append a new version or a deletion marker and have readers keep only the latest. The file then fills with stale versions that something must periodically clean up.

Finished reading?

Saved in this browser only.

Sources

Where each claim on this page comes from.

  1. 1.
    open(2) manual page, macOS
    Primary· O_TRUNC, O_APPEND· man 2 open

    Opening for writing can truncate the file to zero bytes; opening for appending places every write at the end of the file.

Go further

What to read next, and why it is worth the time.

  1. 1.
    Designing Data-Intensive Applications
    ReferenceMartin Kleppmann· Chapter 3: Storage and Retrieval, Data Structures That Power Your Database· location not yet verified

    Starts from a two-line "database" that appends to a file, then shows how indexes, compaction and B-trees grow out of exactly the costs on this page.

Applies to macOS or Linux, Python 3. Draft: not yet fact-checked end to end.