MasterRecord

Best Practices

Hard-won patterns for production apps.

MasterRecord is flexible, but a few conventions keep your code fast, correct, and easy to reason about.

1. Always await writes#

Saving is asynchronous on MySQL and Postgres. Await every save() and saveChanges() so errors surface and ordering is guaranteed.

javascript
await user.save();          // ✅
await db.saveChanges();     // ✅
user.save();                // ❌ unhandled promise, lost errors

2. Define fields as methods#

Columns are builder methods, not constructor properties. Object-literal “fields” are silently ignored by the schema builder.

javascript
name(db) { db.string().notNullable(); }   // ✅
// this.name = { type: 'string' };         ❌ ignored

3. Name the context file after the class#

The migration CLI resolves contexts by file name. Keep AppContext in app/models/AppContext.js so master db can find it.

4. Use relative SQLite paths#

connection: 'db/' resolves under your project root and auto-creates the file. A leading slash (/db/) is treated as a filesystem-absolute path.

5. Parameterize — never concatenate#

Bind values with $$. The query builder parameterizes them, eliminating injection.

javascript
db.User.where((u) => u.email == $$, email);   // ✅ safe & parameterized

6. Batch wisely#

Creating many rows? Save them through the same context and call saveChanges() once — MasterRecord builds an optimized batch insert that still runs your .set() transformers and relationships.

7. Index your foreign keys and filters#

Add .index() to columns you filter or join on frequently, and consider full-text indexes for searchable text.

Quick reference
.new() create · .save() persist one · saveChanges() persist all · .where().toList() read many · .single() read one · .remove()/.delete() remove.