2.1 Persistable vs. Non-Persistable Entities
Key Takeaways
- Persistable entities (PEs) map directly to relational database tables, whereas Non-Persistable entities (NPEs) reside exclusively in application server runtime memory.
- Associations between Persistable and Non-Persistable entities can only be owned by the Non-Persistable entity; a Persistable entity cannot own an association to an NPE.
- Committing an NPE does not generate SQL INSERT or UPDATE statements; instead, it synchronizes state with the client runtime and invokes configured event handlers.
- NPEs bound to a user's client session remain in memory until session termination or explicit deletion, creating potential out-of-memory risks if large datasets are loaded into session scope.
2.1 Persistable vs. Non-Persistable Entities
In Mendix domain modeling, entities represent the core data structures of an enterprise application. At the architectural level, every entity is classified as either Persistable (indicated by an orange/yellow entity header in Studio Pro) or Non-Persistable (indicated by a blue/green entity header). Understanding the exact boundary between disk storage and runtime memory is one of the most critical topics tested on the Mendix Intermediate Developer certification exam.
Architectural Mechanics: Database Storage vs. Runtime Memory
When you mark an entity as Persistable, the Mendix Runtime engine generates and maintains a corresponding physical table in the relational database (PostgreSQL, SQL Server, Oracle, or MySQL). Every commit of a persistable object executes transactional SQL statements (INSERT or UPDATE). When the application restarts, persistable records remain safely stored on persistent disk storage.
In contrast, a Non-Persistable Entity (NPE) has no underlying database table. It exists solely as an instantiated Java object within the Java Virtual Machine (JVM) heap memory allocated to the Mendix Runtime. When the application server restarts, or when the object falls out of scope and is collected by the JVM garbage collector, all data within that NPE instance vanishes permanently.
Architectural Comparison
| Feature / Dimension | Persistable Entity (PE) | Non-Persistable Entity (NPE) |
|---|---|---|
| Studio Pro Visual Style | Orange header | Blue / Green header |
| Physical Storage | Relational database table on disk | JVM heap memory in application server |
| Persistence across Restarts | Permanent (survives restarts) | Transient (destroyed on restart) |
| Commit Activity Behavior | Dispatches SQL INSERT / UPDATE | Synchronizes with client; executes events |
| Rollback Activity Behavior | Reverts to last committed DB state | Reverts in-memory values to prior state |
| Database Query Support | Fully queryable via XPath over DB | In-memory filtering only (cannot run SQL) |
| Associated Entity Constraints | Cannot own associations to NPEs | Can own associations to PEs and NPEs |
| Primary Use Cases | Master data, transactions, audit logs | UI wizards, REST payloads, search forms |
Lifecycle, Garbage Collection, and Session Scoping
The lifecycle of a Persistable Entity is governed by standard ACID database transactions. An NPE, however, follows strict memory-lifecycle rules determined by variable scope and client session binding:
1. Microflow-Scoped NPEs (Garbage Collected)
When an NPE is instantiated inside a microflow using a Create Object activity and is never passed to a client page, never returned as an output parameter, and never associated with a long-lived session entity, its reference exists only in the local variable stack of that microflow execution. Once the microflow finishes execution:
- The object reference goes out of scope.
- The JVM Garbage Collector (GC) marks the object as unreferenced.
- The heap memory occupied by the object is reclaimed during the next GC cycle.
2. Session-Bound NPEs (Client State)
When an NPE is passed to a page (e.g., as the page parameter of a Data View), or when it is linked via an association to System.User or a session-persisted object, the Mendix Runtime binds the NPE to the user's active Client Session (SessionId).
- The object remains alive in the runtime memory cache as long as the user's session is active.
- It is automatically transferred across network boundaries between the client browser and runtime.
- It is purged only when explicitly removed via a
Delete Objectaction, when the user logs out, or when the session times out due to inactivity.
The Association Direction Rule: Why NPEs Must Own Associations
A critical rule enforced by the Studio Pro domain model consistency checker governs associations between Persistable and Non-Persistable entities:
The Golden Rule of Hybrid Associations: An association between a Persistable Entity and a Non-Persistable Entity must always be owned by the Non-Persistable Entity.
Why This Rule Exists
In a relational database, an association is physically implemented by placing a foreign key column in the owner entity's table (for 1-to-1 and 1-to-Many associations) or by generating a join table (for Many-to-Many associations).
If a Persistable entity owned an association pointing to an NPE, the relational database would need to write a foreign key value into its physical table referencing a record that does not exist in any database table. Because an NPE has only a transient, in-memory pointer that changes on every server boot and does not exist in relational storage, foreign key constraints would be violated.
Conversely, when the NPE owns the association, the reference is stored entirely in memory. The NPE simply holds the primary key ID of the persistable database record in its JVM memory heap. The Mendix Runtime can effortlessly resolve this reference by issuing a database SELECT against the persistable table using the stored ID whenever the association is traversed.
What the "Commit" Action Truly Does for Non-Persistable Entities
Intermediate developers frequently wonder why Studio Pro allows executing a Commit Object action on an NPE if no database table exists.
When you execute Commit Object on an NPE:
- Client Synchronization: The runtime marks the object as clean and serializes the modified attribute values down to the client browser, updating any bound widgets on the user's screen.
- Event Handlers: If any entity-level event handlers (such as Before Commit or After Commit) are defined, they execute in the specified sequence.
- Rollback Baseline: The committed state becomes the new baseline. If a subsequent
Rollback Objectaction is triggered in the same session, the NPE reverts to this committed in-memory state rather than its initial state. - No SQL Dispatched: Crucially, the database connection pool is never touched. No SQL transactions, locks, or table writes occur.
Four High-Value Use Cases for Non-Persistable Entities
Using NPEs strategically prevents database bloat, eliminates locking overhead, and dramatically speeds up application response times. The four canonical architectural patterns are:
1. Multi-Step Wizard State Holders
When building multi-page onboarding, booking, or loan application wizards, users frequently abandon the flow midway through. If persistable entities are created on step 1, abandoned sessions leave orphaned, incomplete records in the database that require complex cleanup jobs. By holding the wizard's state in a single session-scoped NPE, nothing touches the database until the final "Submit" button is clicked. If the user closes their browser, the memory is naturally freed on session expiry.
2. Integration Payloads & Mappings (REST / SOAP)
Modern microservices exchange complex, deeply nested JSON or XML payloads. Mapping a 50-field JSON response directly into persistable entities incurs massive disk write overhead for data that might only be read once to display a live rate quote. Using NPEs for Import and Export mappings processes payloads entirely in memory at lightning speed.
3. Dynamic Search and Filter Contexts
When implementing custom search screens with multiple dropdowns, date pickers, and checkboxes, creating a SearchContext NPE allows binding UI input widgets directly to entity attributes without persisting temporary search filters to the database. A microflow retrieves the SearchContext object, constructs an optimized XPath query, and returns the filtered persistable results.
4. Temporary Calculation & Dashboard Aggregations
When generating dynamic charts or intermediate reporting metrics (such as grouping sales data by territory for live visualization), storing the calculated slices in NPEs allows the UI to render charts efficiently without polluting transactional database tables with ephemeral summary data.
Memory Pitfalls & Production Traps
While NPEs are powerful, misuse in production environments can lead to catastrophic JVM OutOfMemoryError failures:
- The Unbounded List Trap: Retrieving 100,000 records from an external service into NPEs simultaneously can consume several gigabytes of JVM heap space. Always process large datasets in batches or use pagination.
- Dangling Session References: Associating thousands of NPEs to the user's
SessionorAccountentity prevents the garbage collector from reclaiming them. The memory remains occupied until the user explicitly logs out. - Network Payload Bloat: Because the Mendix client synchronizes session NPEs across the web socket or HTTP connection, creating overly complex NPE trees bound to a page slows down client rendering and saturates mobile bandwidth.
When modeling an association between a persistable entity (Customer) and a non-persistable helper entity (OrderWizardContext), what constraint does Mendix Studio Pro strictly enforce regarding association ownership?
A developer executes a Commit Object activity on a Non-Persistable Entity (NPE) inside a microflow. What occurs during runtime execution?
An integration microflow retrieves 50,000 records from an external REST API, converts them into Non-Persistable Entities (NPEs), performs an in-memory aggregation, and returns a single numerical total without associating the NPEs to any session object or page. What happens to the 50,000 NPE instances?