Enfyra is the open-source backend platform.
We’re building the flexibility backend framework that automatically generates APIs from your database. You create tables through a visual interface, and Enfyra instantly provides REST & GraphQL APIs for them - no coding required. It's like having a backend developer that never sleeps.
For full documentation, visit docs
To see how to contribute, visit Contributing
Architecture
Enfyra is a self-hosted and locally developed, easy-to-install. Cloud coming soon.
- Query Engine: high-performance engine for filtering, joins, aggregates, and search directly through your API.
- Realtime: push updates to clients when rows change using websockets.
- REST/GraphQL API: automatically generated from your schema.
- Auth Service: JWT-based authentication API for sign-ups, logins, and session management.
- Storage: RESTful API for managing files and permissions.
- Functions: run server-side code close to your data.
Enfyra supports schema and data migrations through JSON configuration files.
Define your database schema (tables, columns, relations):
{
"my_table": {
"name": "my_table",
"description": "My custom table",
"columns": [
{ "name": "id", "type": "int", "isPrimary": true, "isGenerated": true },
{ "name": "name", "type": "varchar", "isNullable": false }
],
"relations": []
}
}Run schema migration:
npx ts-node scripts/init-db.tsFor dangerous operations (remove, modify/rename). Adding is handled automatically by snapshot.json.
{
"tables": [
{
"_unique": { "name": { "_eq": "users" } },
"columnsToModify": [
{ "from": { "name": "email" }, "to": { "name": "userEmail" } }
],
"columnsToRemove": ["deprecated_field"],
"relationsToModify": [
{ "from": { "propertyName": "oldRelation" }, "to": { "propertyName": "newRelation" } }
],
"relationsToRemove": ["deprecated_relation"]
}
],
"tablesToDrop": ["old_table_name"]
}Operations:
| Field | Description | Data Loss Risk |
|---|---|---|
columnsToModify |
Rename or change column properties | Low (rename preserves data) |
columnsToRemove |
Remove columns | HIGH |
relationsToModify |
Rename or change relation properties | Low |
relationsToRemove |
Remove relations (drops FK column) | HIGH |
tablesToDrop |
Drop entire tables | HIGH |
Flow:
- Physical DB changes (init-db script or app bootstrap)
- Metadata updates (provision service)
- Both read from same
snapshot-migration.json→ consistent
1. Rename a column (preserves data)
{
"tables": [{
"_unique": { "name": { "_eq": "users" } },
"columnsToModify": [
{ "from": { "name": "email" }, "to": { "name": "userEmail" } }
]
}]
}Result: Column email renamed to userEmail, data preserved.
2. Change column properties
{
"tables": [{
"_unique": { "name": { "_eq": "users" } },
"columnsToModify": [
{
"from": { "name": "status", "isNullable": true },
"to": { "name": "status", "isNullable": false }
}
]
}]
}Result: Column status becomes NOT NULL.
3. Remove deprecated column (
{
"tables": [{
"_unique": { "name": { "_eq": "users" } },
"columnsToRemove": ["old_legacy_field"]
}]
}Result: Column old_legacy_field dropped, all data in this column lost.
4. Rename a relation (preserves FK data)
{
"tables": [{
"_unique": { "name": { "_eq": "orders" } },
"relationsToModify": [
{ "from": { "propertyName": "approvedBy" }, "to": { "propertyName": "approver" } }
]
}]
}Result: FK column approvedById renamed to approverId, data preserved.
5. Remove a relation (
{
"tables": [{
"_unique": { "name": { "_eq": "orders" } },
"relationsToRemove": ["legacyRelation"]
}]
}Result: FK column dropped, all FK references lost.
6. Drop entire table (
{
"tablesToDrop": ["deprecated_table", "legacy_data"]
}Result: Tables completely removed from database.
| Scenario | File to Modify |
|---|---|
| Add new table | snapshot.json |
| Add new column | snapshot.json |
| Add new relation | snapshot.json |
| Rename column | snapshot-migration.json |
| Remove column | snapshot-migration.json |
| Rename relation | snapshot-migration.json |
| Remove relation | snapshot-migration.json |
| Drop table | snapshot-migration.json |
┌─────────────────────────────────────┐
│ snapshot-migration.json │
│ (single source) │
└──────────────┬──────────────────────┘
│
┌───────┴───────┐
▼ ▼
┌──────────────┐ ┌──────────────────┐
│ init-db.ts │ │ provision service│
│ │ │ (app bootstrap) │
│ Physical DB │ │ Metadata DB │
│ (tables, │ │ (table_def, │
│ columns, │ │ column_def, │
│ FKs) │ │ relation_def) │
└──────────────┘ └──────────────────┘
│ │
└───────┬───────┘
▼
✅ Consistent
Both physical DB and metadata are updated from the same source, ensuring consistency.
Migrate existing data when the system is already initialized:
{
"_deletedTables": ["deprecated_table"],
"role_definition": [
{
"name": "Admin",
"description": "Updated admin description",
"_unique": { "name": { "_eq": "Admin" } }
}
]
}_deletedTables: Array of table names to delete all data from- Table entries: Data to migrate, using
_uniqueto identify existing records
-
First Init (
isInit = false):- Schema is created from
snapshot.json - Default data is inserted from
default-data.json - System sets
isInit = true
- Schema is created from
-
Subsequent Starts (
isInit = true):- Schema is synced from
snapshot.json(auto-add new columns/relations) - Schema migrations run from
snapshot-migration.json(remove/modify) - Data migrations run from
data-migration.json
- Schema is synced from
- SQL: MySQL, PostgreSQL, MariaDB
- NoSQL: MongoDB