Choosing the Right State Store for K3s: SQLite vs. External Databases
K3s uses SQLite by default to reduce the memory overhead of etcd. Learn when to stick with SQLite for edge devices and when to migrate to an external database for high availability.
07 Dec 2025, 08:48 UTC

The Resource Tax of Cluster State
Standard Kubernetes requires etcd, a distributed key-value store that ensures consistency across a cluster. While powerful, etcd is resource-heavy, requiring significant memory and disk I/O to maintain its quorum. For edge computing or small-scale development environments, the overhead of etcd can consume a disproportionate amount of the available system resources, leaving little room for the actual workloads.
K3s solves this by replacing etcd with SQLite by default. The takeaway for engineers is simple: if you are running a single-node cluster or a resource-constrained edge device, SQLite removes the etcd tax. However, if you need high availability (HA) or high write concurrency, you must pivot to an external database.
How K3s Mimics etcd with Kine
Kubernetes is hard-coded to expect an etcd-compatible API. To use SQLite without rewriting the core Kubernetes codebase, K3s uses a wrapper called Kine.
Kine acts as a translation layer. When the Kubernetes API server sends a request to store a pod definition, Kine intercepts that etcd-style call and translates it into a SQL query that SQLite understands. This allows K3s to maintain a standard Kubernetes API while using a lightweight file-based database on the backend.
Comparing State Store Options
Choosing between the default SQLite setup and an external database depends on your failure domain and scale requirements.
| Feature | SQLite (Default) | External DB (PostgreSQL/MySQL) |
|---|---|---|
| Footprint | Minimal (single file) | Moderate to High |
| Availability | Single Point of Failure | High Availability (HA) |
| Write Speed | Low (Sequential) | High (Concurrent) |
| Complexity | Zero Configuration | Requires DB Management |
When to stick with SQLite
- Edge Deployments: Running on ARM devices or Raspberry Pis where RAM is limited.
- CI/CD Pipelines: Spin-up/tear-down clusters for automated testing.
- Local Development: Testing manifests before deploying to a production cloud environment.
When to migrate to an External DB
- Multi-Server Control Planes: When you need multiple server nodes to share state for redundancy.
- High Object Churn: Environments with frequent scaling events or many short-lived pods that create heavy write pressure.
Configuration Example: Moving to PostgreSQL
To move from SQLite to a high-availability setup, you must provide the database connection string during the server installation. This should be run on the server node with root or sudo permissions.
# Install K3s server pointing to an external PostgreSQL instance
curl -sfL https://get.k3s.io | sh -s - server \
--datastore-endpoint="postgres://username:password@postgres-host:5432/k3s_db"
Expected Check: After installation, check the server logs to ensure the connection is established. You can run journalctl -u k3s | grep "datastore". If the connection fails, the K3s process will crash and restart, as it cannot initialize the cluster state without the database.
Limitations and Trade-offs
The primary limitation of SQLite is the lack of a distributed consensus mechanism. In a standard etcd cluster, nodes vote to agree on the state. SQLite is a local file; if the node hosting that file dies, the cluster state is inaccessible until the disk is recovered or restored from a backup.
Additionally, SQLite handles concurrent writes poorly. If your automation scripts are creating and deleting hundreds of resources per minute, you may encounter database locks, leading to API latency.
Verifying Your State Store
To verify which datastore your current K3s installation is using, inspect the process arguments on the server node:
# Run as root on the server node
ps aux | grep k3s | grep datastore
If no --datastore-endpoint flag is present, K3s is using the default SQLite database located at /var/lib/rancher/k3s/server/db/.
Rollback Procedure
If you migrate to an external database and need to revert to SQLite, you cannot simply remove the flag. You must uninstall K3s, delete the existing state directory to avoid conflicts, and reinstall without the endpoint flag:
- Run
/usr/local/bin/k3s-uninstall.sh. - Remove the state directory:
rm -rf /var/lib/rancher/k3s. - Reinstall using the standard
curl -sfL https://get.k3s.io | sh -command.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.