Python

Python TinyDB Tutorial | Lightweight Database Guide

Master lightweight JSON storage with TinyDB for your Python applications – installation, setup, and practical examples included

By InventiveHQ Team

What is TinyDB?

TinyDB is a pure-Python, document-oriented database that stores your data as a single human-readable JSON file — with no server, no schema definition, and no dependencies beyond the standard library. You install it with pip install tinydb, create a database with one line (db = TinyDB('data.json')), and immediately insert, query, update, and delete Python dictionaries. It is the right tool for prototypes, command-line utilities, config storage, and small apps holding up to roughly 10,000 documents; past that point its maintainers explicitly recommend moving to SQLite, because TinyDB loads and rewrites the whole file in Python rather than using indexes.

That's the summary an AI Overview can give you. What it can't show you is where TinyDB fits versus the alternatives you'll actually compare it against, the exact five-step lifecycle of a TinyDB app, and the one API change that breaks almost every older tutorial online. Those are below — a decision table, an animated flow diagram, and a working end-to-end script tested against the current TinyDB 4.x API.

TinyDB vs. SQLite vs. shelve vs. a plain JSON file

The real question is never "how do I use TinyDB" — it's "should I use TinyDB or one of the three things it's usually mistaken for." Here is the honest comparison:

FactorTinyDBSQLite (sqlite3)shelvePlain JSON file
Storage formatHuman-readable JSONBinary .db fileBinary pickleHuman-readable JSON
Query languagePython Query objectsFull SQLKey lookup onlyManual dict/list code
Indexes / speed at scaleNone — linear scanB-tree indexes, very fastKey-based onlyNone
Schema requiredNoYes (tables/columns)NoNo
Dependenciespip install tinydbBuilt into PythonBuilt into PythonBuilt into Python
Concurrent writesNot safe (rewrites file)Safe (locking, WAL)Not safeNot safe
Practical ceiling~10,000 documentsMillions of rowsSmall key setsA few hundred KB
Use it when…You want queryable, readable storage for a small app or prototype fastYou need speed, indexes, or concurrent accessYou just need to persist Python objects by keyYou have static config or a tiny flat list

The short version: if you're reaching for a JSON file and finding yourself writing loops to filter it, TinyDB is the upgrade. If you're pushing past ~10k records, feeling slow queries, or need multiple writers, SQLite is the upgrade from TinyDB.

The TinyDB lifecycle at a glance

Every TinyDB program follows the same five-stage loop. This diagram shows it end to end:

The five stages of a TinyDB application lifecycle Connect creates or opens the JSON file, Insert adds dictionaries, Query filters with Query objects, Update or Remove modifies matching documents, and every write is flushed back to the same JSON file on disk. 1. Connect TinyDB('data.json') opens / creates file 2. Insert db.insert(dict) adds a document 3. Query db.search(Q.field == x) filter documents 4. Update / Remove modify matches 5. Persist auto-written to JSON on disk Reopen the file next run — your data is still there

Every write is flushed to the same JSON file; there is no separate "save" or "commit" step.

Key advantages of TinyDB include:

  • Zero configuration required
  • Human-readable JSON storage format
  • Built-in query system
  • Thread-safe operations
  • Pure Python implementation
Advertisement

Installing TinyDB

Before installing TinyDB, it's recommended to set up a virtual environment for your Python project. This ensures clean dependency management and prevents conflicts with other projects.

# For Python 3
pip install tinydb

# Alternative for systems with both Python 2 and 3
pip3 install tinydb

If you don't have pip installed or are unsure which Python version you're using, check out our comprehensive Python Basics guide for setup instructions.

Getting Started with TinyDB

TinyDB operates entirely with JSON data structures using key/value pairs. For this tutorial, we'll build a to-do list application that stores:

  • Task description
  • Due date
  • Completion status
  • Category classification

Basic Setup

# Import TinyDB and Query modules
from tinydb import TinyDB, Query

# Create database instance (creates todolist.json file)
db = TinyDB('todolist.json')

# Define sample records
item1 = {'Status':'New','DueDate': '5/12/18', 'Category': 'Work','Description':'Send that Email'}
item2 = {'Status':'New','DueDate': '5/11/18', 'Category': 'Home','Description':'Do the Laundry'}
item3 = {'Status':'New','DueDate': '5/11/18', 'Category': 'Home','Description':'Do the Dishes'}

Inserting Records

Adding data to TinyDB is straightforward using the insert() method. You can insert predefined variables or create records directly within the function call:

# Insert using predefined variables
db.insert(item1)
db.insert(item2)
db.insert(item3)

# Insert directly without variables
db.insert({'Status':'New','DueDate': '5/14/18', 'Category': 'Work','Description':'Request a Promotion'})

# Verify insertion by displaying all records
print(db.all())

Searching and Querying Records

TinyDB provides powerful search capabilities for filtering records based on specific criteria. Here are common search patterns:

# Create Query object
Todo = Query()

# Single criteria search
home_tasks = db.search(Todo.Category == 'Home')

# Multiple criteria with AND condition
work_urgent = db.search((Todo.Category == 'Work') & (Todo.DueDate == '5/14/18'))

# Multiple criteria with OR condition
urgent_or_home = db.search((Todo.Category == 'Home') | (Todo.DueDate == '5/14/18'))

# Store search results and iterate
results = db.search(Todo.Category == 'Home')
for result in results:
    print(result)

Updating and Deleting Records

TinyDB makes it easy to update existing records or remove completed tasks from your database:

Updating Records

# Update all Home category tasks to Done status
db.update({'Status': 'Done'}, Todo.Category == 'Home')

Deleting Records

# Remove all completed tasks
db.remove(Todo.Status == 'Done')

# Clear entire database (useful for testing)
db.truncate()

Watch out — the db.purge() trap. If you follow an older tutorial, you'll see db.purge() used to empty the database. That method was removed in TinyDB 4.0 (February 2020) and now raises AttributeError: 'TinyDB' object has no attribute 'purge'. On any current version (4.x and later), use db.truncate() to clear all records. This single rename is the most common reason copied TinyDB snippets fail today.

Complete Example Script

Here's a comprehensive example that demonstrates all TinyDB operations in a single script:

# Complete TinyDB example script
from tinydb import TinyDB, Query

# Initialize database
db = TinyDB('todolist.json')
Todo = Query()

# Create sample data
item1 = {'Status':'New','DueDate': '5/12/18', 'Category': 'Work','Description':'Send that Email'}
item2 = {'Status':'New','DueDate': '5/11/18', 'Category': 'Home','Description':'Do the Laundry'}
item3 = {'Status':'New','DueDate': '5/11/18', 'Category': 'Home','Description':'Do the Dishes'}

# Insert records
db.insert(item1)
db.insert(item2)
db.insert(item3)
db.insert({'Status':'New','DueDate': '5/14/18', 'Category': 'Work','Description':'Request a Promotion'})

# Display all records
print("All records:")
print(db.all())

# Update Home category tasks to Done
db.update({'Status': 'Done'}, Todo.Category == 'Home')

# Search and display Home category tasks
print("\nHome category tasks:")
results = db.search(Todo.Category == 'Home')
for result in results:
    print(result)

# Remove completed tasks
db.remove(Todo.Status == 'Done')

# Show remaining records
print("\nRemaining records:")
print(db.all())

Best Practices and Tips

💡 Pro Tips for TinyDB Success

  • Use descriptive field names for better code readability
  • Implement data validation before inserting records
  • Consider using TinyDB's memory storage for temporary data
  • Back up your JSON files regularly in production environments
  • Use the truncate() method (not the removed purge()) during testing to reset your database
  • Move to SQLite once you cross ~10,000 documents or need concurrent writers — see the comparison table above

When to graduate off TinyDB

TinyDB earns its place at the start of a project. The moment you notice queries lagging, the JSON file ballooning past a megabyte or two, or a second process trying to write at the same time, those are the signals to migrate. Python's built-in sqlite3 module is the natural next step: it keeps your data in a single file like TinyDB, needs no server, but adds real indexes, SQL, and safe concurrent access. Because your TinyDB records are already plain dictionaries, exporting them to SQLite rows or to CSV is usually a short loop — and if you're moving between formats often, our JSON-to-CSV conversion guide covers the round trip.

Frequently Asked Questions

What is TinyDB used for in Python?

TinyDB is a document-oriented database that stores data as a single JSON file, with no server, no schema, and no external dependencies. It is used for small apps, prototypes, CLI tools, config storage, and scripts where you need queryable persistence but a full database like SQLite or PostgreSQL would be overkill. Its official guidance caps practical use at roughly 10,000 documents before query performance degrades.

Is TinyDB faster than SQLite?

No. For anything beyond a few thousand records, SQLite is dramatically faster because it uses indexed B-trees and a compiled C engine, while TinyDB loads and scans the entire JSON file in Python for most queries. TinyDB wins only on setup simplicity and human-readable storage, not on speed or scale.

Why was db.purge() removed from TinyDB?

db.purge() was removed in TinyDB 4.0 (released February 2020). To delete all records in TinyDB 4.x and later, use db.truncate() instead. Tutorials that still call db.purge() were written for TinyDB 3.x and will raise an AttributeError on current versions.

How do I query multiple conditions in TinyDB?

Combine Query objects with the bitwise operators & (AND), | (OR), and ~ (NOT), and wrap each condition in parentheses. For example, db.search((Todo.Category == 'Work') & (Todo.Status == 'New')) returns work tasks that are still new. You must use & and |, not the Python keywords and and or, because those do not work on Query objects.

Where does TinyDB store its data?

By default TinyDB writes to the JSON file path you pass to the constructor, for example TinyDB('todolist.json'), creating it in the current working directory if it does not exist. You can also use the in-memory MemoryStorage backend for temporary data that disappears when the program exits.

Is TinyDB thread-safe?

TinyDB is not safe for concurrent writes from multiple processes or threads out of the box, because it rewrites the whole JSON file on each change. For multi-threaded access you must add your own locking, and for multi-process or web-server workloads you should use SQLite or a client-server database instead.

How do I update a record without overwriting other fields in TinyDB?

Pass a partial dictionary to db.update() with a query, for example db.update({'Status': 'Done'}, Todo.Category == 'Home'). Only the keys you provide are changed; all other fields in the matching documents are preserved. To modify a value based on its current value, pass a callable instead of a dictionary.

Can TinyDB handle large datasets?

Not efficiently. Because TinyDB reads and rewrites the entire JSON file for most operations, memory use and latency grow with file size. The maintainers recommend switching to SQLite or another engine past about 10,000 documents or a few megabytes of data.