---
title: "SQLite Internals: Pages & B-trees"
description: "SQLite stores table rows as encoded byte arrays, and understanding that representation explains how a simple database preserves compact records and supports efficient growth. Using a sandwich table as an example, the post decodes a row’s varints, type values, UTF-8 text, IEEE-754 floating-point value, and integer count, then examines 4KB pages, cell-pointer indexes, and page headers. SQLite’s b+tree places records in leaf pages and key-range indexes in interior pages; page splits add levels as the database grows, while searches traverse only one page per tree level. The examples estimate that a depth-four tree can hold about 500³ leaf pages, or roughly 476GB, while requiring four page reads for a lookup. The discussion concludes that integer storage is more space-efficient than floating-point storage and that internals such as record encoding and PRAGMAs become less opaque when understood."
---

# SQLite Internals: Pages & B-trees

[Fly.io](https://yomu.fyi/company/fly-io) · Jul 27, 2022

**Type:** Explainer

## Summary

SQLite stores table rows as encoded byte arrays, and understanding that representation explains how a simple database preserves compact records and supports efficient growth. Using a sandwich table as an example, the post decodes a row’s varints, type values, UTF-8 text, IEEE-754 floating-point value, and integer count, then examines 4KB pages, cell-pointer indexes, and page headers. SQLite’s b+tree places records in leaf pages and key-range indexes in interior pages; page splits add levels as the database grows, while searches traverse only one page per tree level. The examples estimate that a depth-four tree can hold about 500³ leaf pages, or roughly 476GB, while requiring four page reads for a lookup. The discussion concludes that integer storage is more space-efficient than floating-point storage and that internals such as record encoding and PRAGMAs become less opaque when understood.

## Context

The post aims to explain what happens between inserting a row and saving its bytes to disk, including how SQLite updates and searches data efficiently as a database grows. It uses a sandwich database to make record formatting, pages, and b+trees concrete.

## Approach / What changed

It decodes a sample SQLite record format, covering varints, column type encodings, UTF-8 text, IEEE-754 floating-point storage, and integer storage. It then explains 4KB page layouts, cell pointers, leaf and interior pages, b+tree traversal, and page splitting as the tree expands.

## Takeaways

- SQLite varints use the high bit as a continuation flag and the remaining seven bits for data, allowing integers such as 1,000 to occupy two bytes instead of eight.
- SQLite stores rows in 4KB pages, with cell pointers indexing record offsets while row data is packed from the end of the page backward.
- A depth-four b+tree can hold about 500³ leaf pages, or roughly 476GB, while a lookup requires at most four page reads in the example.

**Tags:** [Databases](https://yomu.fyi/topic/databases), [SQLite](https://yomu.fyi/topic/sqlite)

- Source: [Fly.io](https://fly.io/blog/sqlite-internals-btree)
- Source URL: https://fly.io/blog/sqlite-internals-btree
- Ingested by Yomu: 2026-09-02T11:58:09.451Z

[Read original post](https://fly.io/blog/sqlite-internals-btree)
