DEV Community

Alex Spinov
Alex Spinov

Posted on

PocketBase Has a Free API: A Backend in a Single Executable File

PocketBase is an open-source backend that comes as a single executable file. It includes a database (SQLite), authentication, file storage, and real-time subscriptions — all in one 15MB binary.

Why PocketBase Matters

Setting up a backend typically means: database server, auth service, file storage, API framework, and deployment configs. PocketBase replaces ALL of it with one file you can run anywhere.

What you get for free:

  • RESTful API auto-generated from your schema
  • Real-time subscriptions via SSE
  • Built-in authentication (email, OAuth2)
  • File storage with thumbnails
  • Admin dashboard UI
  • Single executable, zero dependencies
  • SQLite database (embedded)
  • Go and JavaScript/Dart SDKs

Quick Start

# Download single binary
wget https://github.com/pocketbase/pocketbase/releases/latest/download/pocketbase_linux_amd64.zip
unzip pocketbase_linux_amd64.zip

# Run (that is literally it)
./pocketbase serve

# Admin UI: http://127.0.0.1:8090/_/
# API: http://127.0.0.1:8090/api/
Enter fullscreen mode Exit fullscreen mode

JavaScript SDK

import PocketBase from "pocketbase";

const pb = new PocketBase("http://127.0.0.1:8090");

// Authentication
await pb.collection("users").authWithPassword("user@example.com", "password123");

// Create record
const post = await pb.collection("posts").create({
  title: "Hello PocketBase",
  content: "This is my first post",
  author: pb.authStore.model.id,
});

// List with filtering
const posts = await pb.collection("posts").getList(1, 20, {
  filter: 'created >= "2024-01-01"',
  sort: "-created",
  expand: "author",
});

// Real-time subscriptions
pb.collection("posts").subscribe("*", (e) => {
  console.log(e.action); // create, update, delete
  console.log(e.record);
});

// File upload
const formData = new FormData();
formData.append("title", "Photo Post");
formData.append("image", fileInput.files[0]);
const record = await pb.collection("posts").create(formData);

// Get file URL
const url = pb.files.getURL(record, record.image);
Enter fullscreen mode Exit fullscreen mode

React Integration

import { useEffect, useState } from "react";
import PocketBase from "pocketbase";

const pb = new PocketBase("http://127.0.0.1:8090");

function PostList() {
  const [posts, setPosts] = useState([]);

  useEffect(() => {
    // Load initial data
    pb.collection("posts").getFullList({ sort: "-created" })
      .then(setPosts);

    // Subscribe to changes
    pb.collection("posts").subscribe("*", (e) => {
      if (e.action === "create") {
        setPosts((prev) => [e.record, ...prev]);
      }
    });

    return () => pb.collection("posts").unsubscribe();
  }, []);

  return (
    <ul>
      {posts.map((post) => (
        <li key={post.id}>{post.title}</li>
      ))}
    </ul>
  );
}
Enter fullscreen mode Exit fullscreen mode

Extend with Go

package main

import (
    "log"
    "github.com/pocketbase/pocketbase"
    "github.com/pocketbase/pocketbase/core"
)

func main() {
    app := pocketbase.New()

    // Add custom route
    app.OnServe().BindFunc(func(se *core.ServeEvent) error {
        se.Router.GET("/api/custom/stats", func(e *core.RequestEvent) error {
            records, _ := app.FindAllRecords("posts")
            return e.JSON(200, map[string]int{"total": len(records)})
        })
        return se.Next()
    })

    // Hook: before create
    app.OnRecordCreate("posts").BindFunc(func(e *core.RecordEvent) error {
        e.Record.Set("slug", slugify(e.Record.GetString("title")))
        return e.Next()
    })

    log.Fatal(app.Start())
}
Enter fullscreen mode Exit fullscreen mode

Deployment

# It is literally one file. Deploy anywhere:
scp pocketbase user@server:/opt/pocketbase/
ssh user@server '/opt/pocketbase/pocketbase serve --http=0.0.0.0:8090'

# Or Docker
FROM alpine:latest
COPY pocketbase /usr/local/bin/
EXPOSE 8090
CMD ["pocketbase", "serve", "--http=0.0.0.0:8090"]
Enter fullscreen mode Exit fullscreen mode

Links


Building data backends? Check out my developer tools on Apify or email spinov001@gmail.com for custom solutions.

Top comments (0)