Hi there! I'm Maneshwar. Right now, I’m building LiveAPI, a first-of-its-kind tool that helps you automatically index API endpoints across all your repositories. LiveAPI makes it easier to discover, understand, and interact with APIs in large infrastructures.
Most people set up Parse Server and just roll with it — add classes from the dashboard, tweak fields on the fly, and rely on the schema to “just work.”
But in production? You need control. You need structure. You need schema definitions in code, not ad-hoc changes in a GUI.
Here's how to fully define and lock your Parse Server schema using JavaScript.
Schema Definitions in Code
You can define every class and field explicitly in your Node.js codebase. Here's what a _User
and OrgMember
class look like:
const UserSchema = [
{
className: "_User",
fields: {
objectId: { type: "String" },
createdAt: { type: "Date" },
updatedAt: { type: "Date" },
ACL: { type: "ACL" },
username: { type: "String" },
password: { type: "String" },
email: { type: "String" },
emailVerified: { type: "Boolean" },
authData: { type: "Object" },
first_name: { type: "String" },
last_name: { type: "String" },
aadhaarStatus: { type: "String" },
profilePicUrl: { type: "String", required: false },
sessionPointer: {
type: "Pointer",
targetClass: "_Session",
required: false,
},
stripeCustomerId: { type: "String", required: false },
location: { type: "String", required: false },
profilePic: { type: "String" },
verificationToken: { type: "String", required: false },
appDetail: { type: "String", required: false },
},
classLevelPermissions: {
find: { "*": true },
count: { "*": true },
get: { "*": true },
create: { "*": true },
update: { "*": true },
delete: { "*": true },
addField: { "*": true },
protectedFields: { "*": [] },
},
indexes: {
_id_: { _id: 1 },
username_1: { username: 1 },
email_1: { email: 1 },
},
},
{
className: "OrgMember",
fields: {
objectId: { type: "String" },
createdAt: { type: "Date" },
updatedAt: { type: "Date" },
ACL: { type: "ACL" },
email: { type: "String", required: true },
UserPointer: {
type: "Pointer",
targetClass: "_User",
required: false,
},
onboard_status: { type: "String", required: false },
is_admin: { type: "Boolean", required: false, defaultValue: false },
isActive: { type: "Boolean", required: false, defaultValue: true },
extraParams: { type: "String", required: false },
},
classLevelPermissions: {
find: { requiresAuthentication: true },
count: { requiresAuthentication: true },
get: { requiresAuthentication: true },
create: { requiresAuthentication: true },
update: { requiresAuthentication: true },
delete: { requiresAuthentication: true },
addField: { requiresAuthentication: true },
protectedFields: { "*": [] },
},
indexes: {
_id_: { _id: 1 },
},
},
];
Parse Server Config with Locked Schema
Once you define your schema, plug it into ParseServer.startApp()
:
ParseServer.startApp({
databaseURI: process.env.DATABASE_URI,
appId: process.env.APP_ID,
masterKey: process.env.MASTER_KEY,
serverURL: process.env.SERVER_URL,
port: 1337,
publicServerURL: process.env.SERVER_URL,
schema: {
definitions: UserSchema,
lockSchemas: true,
strict: true,
recreateModifiedFields: false,
deleteExtraFields: false,
},
serverStartComplete: () => {
parseServer.expressApp.get("/ready", (req, res) => {
res.send("true");
});
},
});
Important Flags Explained
lockSchemas: true
→ No schema changes allowed via API. Schema can only change via code.strict: true
→ Any class not listed in your schema will be deleted (be careful!).recreateModifiedFields: false
→ Prevents automatic field type overrides.deleteExtraFields: false
→ Fields not listed in your schema won’t be deleted.
Env Setup Example
DATABASE_URI=postgres://parse:parse@localhost:5433/parse
APP_ID=parse
MASTER_KEY=parse
SERVER_URL=http://localhost:1337/parse
Result
This setup ensures:
- You treat your database schema like code, not UI.
- You get versioned, reviewable schema changes via Git.
- No accidental field changes happen in prod.
Final Tip
Once this is deployed, you can delete any unused classes (like Role
, _Installation
, etc.) from the DB — they won’t come back unless defined in schema.
Use this setup if you're serious about Parse in production with PostgreSQL.
LiveAPI helps you get all your backend APIs documented in a few minutes.
With LiveAPI, you can generate interactive API docs that allow users to search and execute endpoints directly from the browser.
If you're tired of updating Swagger manually or syncing Postman collections, give it a shot.
Top comments (1)
Treating your schema as code is honestly the only way I've found to keep production sane - love how you laid out the config details. Did you run into any headaches migrating old Parse DBs to locked schemas?