Used time based blocks just like the article says. But they also switched if they got larger than 2GB, because it allowed the index offset to be 4 bytes. That allowed pretty fast searching as well as discarding old data.
The data and index and were both written to separate files. Some of the values were not just simple integers/floats but large blobs that's why separate data files.
Decided not to go explicitly with mmap-ing on read. Started that way but abandoned it. A simple pread (read + seek in one syscall) and relying on page caching worked just as well.
Should have used an inverted index for labels, that's a good idea. Maybe just sqlite or something like that... Though my queries were not as free form and some were more common than others. So built custom indices for the common queries.
Index files were also partitioned by time but were synchronized to the same partitioning schedule as the main data file. So if main data file opened a new block file, indices did the same.
Didn't explicitly handle in memory vs not-in memory blocks when writing, but relied on periodic fsync-ing.
Instead of a wal decided that some data that wasn't fsync-ed yet might be lost if power was cut. To deal with corruption on start, data in main file and extra indices were truncated to lasted sane fsync of the main time based index.