Collection and schema design for PocketBase. Use when creating collections, designing schemas, adding fields, setting up relations, or choosing between base/auth/view collection types. Prevents wrong field types, documents zero-default behavior, and covers relation cascading.
Standard data collection. System fields: id, created, updated.
Extends base with authentication. Additional system fields: email, emailVisibility, verified, password, tokenKey.
Cannot delete system fields. Can disable email/password auth in collection options.
Read-only, backed by a SQL SELECT query. No create/update/delete. Fields are auto-detected from the query. Useful for aggregations, joins, and computed views.
-- Example: view collection query
SELECT p.id, p.title, COUNT(c.id) as comments_count
FROM posts p LEFT JOIN comments c ON c.post = p.id
GROUP BY p.id
View collections support API rules (list/view only) and can be used in relations.
| Type | Go type | Zero default | Notes |
|---|---|---|---|
text | string | "" | min/max length, regex pattern |
editor | string | "" | Rich text (sanitized HTML) |
number | float64 | 0 | min/max, noDecimal option |
bool | bool | false | |
email | string | "" | Auto-validated format |
url | string | "" | Auto-validated format |
date | string | "" | ISO 8601 (2024-01-01 00:00:00.000Z) |
select | string/[]string | ""/[] | values list, maxSelect |
file | string/[]string | ""/[] | maxSelect, maxSize, mimeTypes |
relation | string/[]string | ""/[] | collectionId, cascadeDelete, maxSelect |
json | any | null | Only type that can be null! maxSize |
autodate | string | auto | onCreate/onUpdate modifiers |
password | string |
Critical: all types default to their zero value, NOT null. Only json fields can be null.
Use in collection schema definitions:
required — field cannot be empty/zerounique — unique constraint (composite via unique indexes)presentable — included in relation displayhidden — excluded from API responses unless explicitly requested:autogenerate — for text fields: auto-generate value (e.g., slug from other field)posts.author -> users (maxSelect: 1)
Each post has one author. Query posts by author: author = "USER_ID".
posts.tags -> tags (maxSelect: 0, meaning unlimited)
Multi-select relation. Filter: tags ?= "TAG_ID" (contains).
No explicit back-relation field needed. Use @collection.posts.author in API rules or expand from either side:
GET /api/collections/users/records/USER_ID?expand=posts_via_author
Set cascadeDelete: true on the relation field. When the referenced record is deleted, all records pointing to it are also deleted. Default is false (sets to empty string).
A collection can reference itself:
categories.parent -> categories (maxSelect: 1)
CREATE [UNIQUE] INDEX idx_name ON collection (field1, field2)CREATE INDEX ... WHERE conditionEnable per-provider in collection settings. Each provider needs client ID + secret. PocketBase handles the full OAuth2 flow.
Enable in auth collection settings. Sends code via email. Configure otp.enabled, otp.duration, otp.length.
Enable in auth collection settings. Requires a second factor after primary auth. mfa.enabled, mfa.duration, mfa.rule (filter to determine which users need MFA).
Enabled by default. Can customize minPasswordLength. Can disable entirely if using only OAuth2/OTP.
authToken.duration — token lifetime (seconds)passwordAuth.enabled — toggle email/passwordpasswordAuth.identityFields — fields used for login (default: email; can add username)oauth2.enabled — toggle OAuth2otp.enabled — toggle OTPselect over bool when there might be more than 2 states in the futurerelation not text for foreign keys — you get cascade, expand, and type safetyjson fields are schemaless — use sparingly, prefer typed fieldsblog_posts, user_profiles)maxSelect: 1 on relations returns a string ID; maxSelect: >1 or 0 returns an array""| Stored hashed, never returned in API |