Skip to main content
Base collections are the standard collection type in PocketBase. They provide a flexible way to store any kind of structured data with custom fields and validation rules.

When to use base collections

Use base collections when you need to:
  • Store general application data (posts, products, comments, etc.)
  • Create custom data structures without authentication features
  • Build relationships between different data types
  • Store file uploads alongside other data
If you need user authentication, use auth collections instead. For read-only data from SQL queries, use view collections.

Creating a base collection

Create a base collection using the factory function:
collection := core.NewBaseCollection("posts")
This initializes a collection with:
  • Type set to "base"
  • A default id field (15-character lowercase alphanumeric)
  • Empty fields list ready for your custom fields

With a custom ID

You can optionally specify a custom collection ID:
collection := core.NewBaseCollection("posts", "pbc_custom_id")
Collection IDs are automatically generated based on the type and name if not specified. The ID format is pbc_ followed by a CRC32 checksum.

Default fields

Every base collection automatically includes an id field:
&TextField{
    Name:                "id",
    System:              true,
    PrimaryKey:          true,
    Required:            true,
    Min:                 15,
    Max:                 15,
    Pattern:             "^[a-z0-9]+$",
    AutogeneratePattern: "[a-z0-9]{15}",
}
This field:
  • Is automatically generated for new records
  • Cannot be changed after creation
  • Serves as the primary key for the collection
  • Is always required and system-managed

Complete example

Here’s a complete example of creating a blog posts collection:
package main

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

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

    app.OnBootstrap().BindFunc(func(e *core.BootstrapEvent) error {
        // Create the posts collection
        posts := core.NewBaseCollection("posts")

        // Add custom fields
        posts.Fields.Add(
            &core.TextField{
                Name:     "title",
                Required: true,
                Min:      3,
                Max:      200,
            },
            &core.TextField{
                Name:     "slug",
                Required: true,
                Pattern:  "^[a-z0-9-]+$",
                Max:      200,
            },
            &core.EditorField{
                Name:     "content",
                Required: true,
            },
            &core.BoolField{
                Name: "published",
            },
            &core.RelationField{
                Name:         "author",
                Required:     true,
                CollectionId: "users_collection_id",
                MaxSelect:    1,
            },
            &core.RelationField{
                Name:         "categories",
                CollectionId: "categories_collection_id",
                MaxSelect:    5,
            },
            &core.FileField{
                Name:      "featured_image",
                MaxSelect: 1,
                MaxSize:   5242880, // 5MB
                MimeTypes: []string{"image/jpeg", "image/png", "image/webp"},
            },
        )

        // Add indexes for better performance
        posts.AddIndex("idx_slug", true, "`slug`", "")
        posts.AddIndex("idx_published", false, "`published`", "")

        // Set API rules
        posts.ListRule = core.String("")
        posts.ViewRule = core.String("")
        posts.CreateRule = core.String("@request.auth.id != ''")
        posts.UpdateRule = core.String("@request.auth.id = author")
        posts.DeleteRule = core.String("@request.auth.id = author")

        // Save the collection
        if err := e.App.Save(posts); err != nil {
            return err
        }

        return e.Next()
    })

    if err := app.Start(); err != nil {
        log.Fatal(err)
    }
}

Field configuration

Base collections support all available field types. Here are some common patterns:

Text fields with validation

&core.TextField{
    Name:     "username",
    Required: true,
    Min:      3,
    Max:      30,
    Pattern:  "^[a-zA-Z0-9_]+$",
}

Numeric fields with constraints

&core.NumberField{
    Name:     "price",
    Required: true,
    Min:      core.Float64(0),
    Max:      core.Float64(999999.99),
}

Relations to other collections

// Single relation
&core.RelationField{
    Name:         "category",
    Required:     true,
    CollectionId: categoryCollectionId,
    MaxSelect:    1,
}

// Multiple relations
&core.RelationField{
    Name:         "tags",
    CollectionId: tagCollectionId,
    MaxSelect:    10,
}

File uploads

&core.FileField{
    Name:      "attachments",
    MaxSelect: 5,
    MaxSize:   10485760, // 10MB
    MimeTypes: []string{
        "application/pdf",
        "application/msword",
        "text/plain",
    },
}

Setting API rules

Control access to your collection with API rules:
1

Allow public read access

collection.ListRule = core.String("")
collection.ViewRule = core.String("")
2

Require authentication for writes

collection.CreateRule = core.String("@request.auth.id != ''")
3

Owner-only updates and deletes

collection.UpdateRule = core.String("@request.auth.id = owner")
collection.DeleteRule = core.String("@request.auth.id = owner")

Common rule patterns

// Public read, authenticated write
collection.ListRule = core.String("")
collection.ViewRule = core.String("")
collection.CreateRule = core.String("@request.auth.id != ''")
collection.UpdateRule = nil // Deny all
collection.DeleteRule = nil // Deny all

// Owner-based access
collection.ListRule = core.String("")
collection.ViewRule = core.String("")
collection.CreateRule = core.String("@request.auth.id != ''")
collection.UpdateRule = core.String("@request.auth.id = userId")
collection.DeleteRule = core.String("@request.auth.id = userId")

// Role-based access
collection.CreateRule = core.String("@request.auth.role = 'admin'")
collection.UpdateRule = core.String("@request.auth.role = 'admin' || @request.auth.role = 'editor'")
Setting a rule to nil denies all access. Setting it to "" allows all access. Use filter expressions for conditional access.

Adding indexes

Indexes improve query performance for frequently searched fields:
// Unique index on email
collection.AddIndex("idx_unique_email", true, "`email`", "")

// Composite index on multiple fields
collection.AddIndex("idx_user_status", false, "`userId`, `status`", "")

// Conditional index
collection.AddIndex(
    "idx_active_users",
    false,
    "`createdAt`",
    "`status` = 'active'",
)

Index parameters

  • Name: Unique identifier for the index
  • Unique: Whether the index enforces uniqueness
  • Columns: SQL expression for indexed columns (use backticks)
  • Where: Optional WHERE clause for conditional indexes

Updating collections

You can modify existing collections by finding them first:
collection, err := app.FindCollectionByNameOrId("posts")
if err != nil {
    return err
}

// Add a new field
collection.Fields.Add(
    &core.DateField{
        Name: "publishedAt",
    },
)

// Save the changes
if err := app.Save(collection); err != nil {
    return err
}
PocketBase handles schema migrations automatically when you save collection changes. Existing data is preserved when adding new fields.

Best practices

  • Use plural names for collections (posts, users, categories)
  • Use snake_case or camelCase for field names
  • Keep names descriptive but concise

Next steps

Auth collections

Add user authentication to your app

Fields reference

Explore all available field types

View collections

Create read-only SQL-based collections

API rules

Learn about the rule syntax