1.3 Deciding Where Business Logic Runs and Choosing the Right Table Type

Key Takeaways

  • Only Dataverse plug-ins are guaranteed to run regardless of entry point, because they hook the message pipeline instead of a UI surface.
  • Business rules and client-side JavaScript are form-scoped and do not enforce logic on API calls, imports, or other non-UI entry points.
  • Power Automate cloud flows are the right fit for multi-system orchestration and human-in-the-loop approvals, at the cost of asynchronous latency.
  • Standard tables offer the full Dataverse feature set; virtual tables surface external data without duplication; elastic tables (Cosmos DB-backed) handle high-throughput, semi-structured data.
  • Not every external data need requires a table at all — a direct connector call is simpler when Dataverse's relational and security model is not required.
Last updated: July 2026

Two of the most consequential design decisions on any Power Platform project are where business logic executes and which table type stores the data. Getting either wrong shows up later as bugs that only occur through certain entry points, or as a table that cannot scale or cannot reach the data it needs.

Where Should Business Logic Run?

Power Platform offers five distinct places to put logic, each with a different execution guarantee, latency profile, and audience.

OptionExecutesRuns regardless of entry point?Best for
Client-side JavaScriptBrowser, on form eventsNo — form-onlyImmediate UX feedback, field formatting
Business rulesClient and server, per formNo — form-onlySimple show/hide, set value, validation
Dataverse plug-insServer, inside the event pipelineYesLogic that must be enforced universally
Power Automate cloud flowsServer, async orchestrationTrigger-dependentMulti-system workflows, approvals, connectors
Azure Functions / custom codeExternal computeOnly if invoked by a plug-in, flow, or connectorHeavy compute, external SDKs, long-running work

Client-side JavaScript gives the fastest feedback but only fires in a browser session on a specific form — it enforces nothing if a record is created through the Web API or a data import. Business rules are declarative and portable across model-driven forms (including mobile), but their condition logic is intentionally limited and they share the same form-only weakness as JavaScript for anything beyond simple UX.

Plug-ins are the only option that is guaranteed to run no matter how a record enters or changes in Dataverse, because they are registered directly against the Dataverse message pipeline (Create, Update, Delete, and custom messages) rather than against a UI surface. This makes them the correct choice whenever a requirement says "must always" or "regardless of how the record is created."

Power Automate cloud flows are best when the logic is really an orchestration — calling multiple connectors, waiting for a human approval, or coordinating several systems — because that kind of branching, multi-step logic is painful to hand-code in a plug-in and easy to maintain declaratively. The tradeoff is latency: flows run asynchronously outside the transaction, so they cannot block a save the way a synchronous plug-in can.

Azure Functions are reserved for logic that a plug-in or flow cannot practically host — computation that would exceed a plug-in's two-minute synchronous execution limit, or that depends on an external library/SDK not available in the Dataverse sandbox.

Choosing the Right Table Type

Dataverse supports three table storage models plus the option of not storing data in Dataverse at all.

  • Standard tables store rows natively in Dataverse. They get the full platform feature set: relationships (1:N, N:1, N:N), business rules, auditing, offline mobile sync, plug-in triggers on every message, and full security-role enforcement. Default choice for any data the solution owns.
  • Virtual tables map Dataverse table metadata onto data that physically lives in an external system (SQL Server, an OData endpoint, or another line-of-business system) through a data provider. They let model-driven apps, views, and relationships treat external data like a Dataverse table without duplicating or syncing it — the tradeoff is that write support and plug-in trigger coverage depend on what the underlying data provider implements, and many providers are effectively read-focused.
  • Elastic tables are backed by Azure Cosmos DB rather than the standard relational store. They are designed for high-throughput, high-volume, or semi-structured data — telemetry, IoT readings, logs, or JSON payloads with a flexible schema — where a well-chosen partition key matters more than rich relational modeling. Elastic tables trade away some standard-table capabilities (complex relationship types, certain auditing behaviors) in exchange for horizontal scale and configurable retention.
  • No table at all — a connector call. When a solution only needs occasional read or write access to an external system and does not need Dataverse's security model, relationships, or offline behavior applied to that data, calling the source system directly through a standard, premium, or custom connector is simpler than modeling a virtual or standard table for it.

Applying the Decision Together

A realistic design combines both decisions: a "must always enforce" pricing rule belongs in a plug-in against a standard table holding order data, while a high-volume sensor-reading feed is better modeled as an elastic table fed by a cloud flow, and a read-only view of an ERP system's inventory is a strong candidate for a virtual table rather than duplicating that data.

Common Design Mistakes to Avoid

Two mistakes recur often enough to be worth naming explicitly. First, teams sometimes model an external system's data as a full standard table synchronized by a scheduled flow, when a virtual table would have avoided the sync job, the staleness window, and the duplicate storage entirely — virtual tables should be the default question whenever "should we copy this external data into Dataverse?" comes up. Second, teams sometimes push high-volume, short-lived event data (page views, sensor pings, application logs) into a standard table, which then suffers from storage growth and degraded query performance; that data almost always belongs in an elastic table, where retention policies and partition-key design were built for exactly this pattern. Recognizing both mismatches — the wrong table type for external data, and the wrong table type for high-volume data — is a frequent exam scenario.

Test Your Knowledge

A solution needs to store millions of IoT sensor readings per day with a flexible, semi-structured schema and does not need complex Dataverse relationships against this data. Which table type best fits this scenario?

A
B
C
D
Test Your Knowledge

A requirement needs a multi-step process that calls three external systems and pauses for a manager's approval before continuing. Which business logic option is the best fit?

A
B
C
D