Scaling PocketBase: From MVP to Production
Learn strategies for scaling your PocketBase application to handle thousands of concurrent users and millions of records.
Scaling PocketBase: From MVP to Production
A common question we get is: “Can PocketBase scale?” The short answer is yes. The long answer involves understanding architecture, indexing, and resource management.
In this post, we’ll explore how to take a PocketBase app from a weekend prototype to a high-traffic production system.
The SQLite Myth
There’s a misconception that SQLite (PocketBase’s engine) is a “toy” database. In reality, SQLite is the most widely deployed database engine in the world. It powers:
- Every Android & iOS device
- Web browsers (Chrome, Firefox)
- MacOS internals
SQLite can handle huge amounts of data. The “limitation” is usually write concurrency (only one writer at a time), but in WAL mode (which PocketBase uses), this is rarely a bottleneck for typical web apps until you reach massive scale.
Vertical Scaling (The Power of Simplicity)
PocketBase is designed to scale vertically. Because it’s a single Go binary with an embedded database, there is zero network latency between your API and your data.
To scale, you simply create a bigger server.
- MVP: 1 vCPU, 512MB RAM ($5/mo)
- Growth: 2 vCPU, 4GB RAM ($20/mo)
- Production: 4 vCPU, 8GB RAM ($40/mo)
- Enterprise: 16 vCPU, 32GB RAM ($100+/mo)
A high-performance dedicated server running PocketBase can handle 100,000+ realtime connections and 10,000+ requests per second. That’s more than enough for 99% of startups.
Database Optimization
Before buying a bigger server, optimize your data usage.
1. Indexes are Key
If your queries are slow, you’re probably missing an index. Go to Settings > Export collections to export your schema, but managing indexes is currently done via direct SQL or ensuring you indexed fields in the collection editor (searchable fields).
- Note: PocketBase automatically indexes
id,created,updated, and relation fields.
2. Indexes for Filter/Sort
If you frequently run:
pb.collection('posts').getList(1, 10, { filter: 'category = "tech"', sort: '-views' })
You should ensure category and views are indexed.
3. Simplify Relations
Deeply nested relation expansion (expand=user.company.settings) increases
query complexity. Try to denormalize data where appropriate or fetch related
data in separate, simpler queries.
Performance Tips
Use the requestKey
The JS SDK has a request cancellation feature. If a user clicks a button 5 times, previous requests are cancelled.
// This prevents multiple identical checks racing each other
await pb.collection("users").getList(1, 1, {
filter: 'email = "[email protected]"',
requestKey: "email_check",
});
Static vs. Dynamic Content
Use a CDN (like PocketBase Cloud’s CDN or Cloudflare) to cache static assets. Your PocketBase server should only be handling dynamic API requests (JSON).
Limit Fields
Don’t fetch what you don’t need.
pb.collection('posts').getList(1, 20, { fields: 'id,title,slug,author' }) This
reduces JSON parsing overhead and saves bandwidth.
Conclusion
PocketBase scales incredibly well because it eliminates the complexity of distributed systems. For the vast majority of applications, a single vertically scaled server is more performant, cheaper, and easier to maintain than a complex microservices cluster.
Focus on your code efficiency and let raw CPU power handle the rest.