"Dynamics 365 is just slow" is one of the most common complaints I hear as a Technical Architect, and it is almost never true in the way people mean it. What they actually have is a system that has been built up over several years, layer on layer, without anyone stopping to think about what all that customisation does to performance. Dynamics 365 performance problems are nearly always self inflicted, and the good news is that means they are fixable.
I have gone into more than one client site expecting a genuinely difficult platform limitation and found a plugin doing something daft instead. Before you raise a Microsoft support ticket or start blaming Dataverse itself, work through the list below. Nine times out of ten the real cause is sitting somewhere in your own solution.
Start with synchronous plugins doing too much
This is the single biggest cause of slow forms I see, by a wide margin. A synchronous plugin runs on the main thread during save, which means the user is sat staring at a spinner while your plugin does its work. If that plugin is calling out to an external API, running a complex FetchXML query, or looping through related records one at a time, the user feels every millisecond of it.
The fix is usually straightforward once you find the culprit. Anything that does not need to block the save should be asynchronous. Anything calling an external system should have a sensible timeout and should fail gracefully rather than hanging the form. I have seen a single synchronous plugin calling a third party address lookup add four full seconds to every single save on a form used hundreds of times a day. Moving it asynchronous fixed it in an afternoon.
Business rules and JavaScript nobody remembers writing
Forms accumulate business rules and custom JavaScript the way a garage accumulates junk. Somebody adds a rule to hide a field. Somebody else adds an onload script to set a default value. Two years later the form has fourteen business rules and three separate scripts all fighting over the same fields, some of them firing on every single field change across the whole form.
Open your browser developer tools, look at the network tab and the console, and watch what actually fires when you load a form and change a value. It is genuinely eye opening how often you find scripts running that have no reason to still exist, checking conditions that were only ever relevant to a business process the company stopped using a year ago.
Formula and rollup columns that recalculate constantly
Formula columns and rollup fields are brilliant when used sparingly. They become a real problem when a team leans on them as a substitute for proper data modelling, chaining formula columns off other formula columns, or building rollups that aggregate across large numbers of related records. Every one of those has a computation cost, and it adds up across a form, a view, and especially a dashboard that is trying to render dozens of them at once.
If a dashboard feels sluggish, check how many rollup and formula columns it is pulling in before you look anywhere else. Consider whether some of that logic genuinely needs to be live, or whether a scheduled Power Automate flow calculating it periodically would serve the business just as well with a fraction of the load.
Views and queries nobody has looked at in years
Default views in Dynamics 365 get edited constantly, and rarely for the better. Someone adds "just one more column" to a view that is used as a subgrid on a busy form, not realising that column pulls from a related entity and adds a join to every single row rendered. Do that eight times over a few years and your simple subgrid is now running a query with eight unnecessary joins, every time anyone opens that record.
Go through your most used views and subgrids and ask honestly whether every column earns its place. Sort orders on unindexed columns are another quiet killer, particularly on entities with a large number of records. This is unglamorous work, but I have fixed genuinely painful performance complaints just by trimming a handful of views back to what people actually look at.
Integrations hammering the API without thinking about limits
If you are seeing performance problems that come and go rather than a system that is consistently slow, look at your integrations before anything else. A batch job running every few minutes, a badly built middleware layer retrying failed calls without backing off, or a report pulling large datasets during business hours will all create noticeable slowdowns for everyone else using the system at the same time, because they are competing for the same service capacity.
I wrote about this in more detail in my piece on Dynamics 365 service protection limits, but the short version is that Dataverse enforces limits precisely because badly behaved integrations are a common problem. If your integration is regularly bumping into throttling, that is a symptom of a design problem, not something to just build a longer retry loop around.
Plugin trace logs left switched on in production
This one sounds trivial and genuinely is not. Plugin tracing is a fantastic tool while you are actively debugging, and a real drag on performance if it gets left switched on in production. Every trace write is extra work happening on every single plugin execution, across every user, all day long. I have found this exact setting left on in production environments more than once, quietly costing performance for months after the debugging session that needed it had finished.
Environment sizing and where your data actually lives
Occasionally the honest answer is that the environment genuinely needs more capacity, particularly for organisations with very large data volumes or heavy concurrent usage. But check this last, not first. I have watched teams throw money at bigger environments and premium add ons when the actual problem was a synchronous plugin nobody had looked at properly. Fix the things within your control before you assume you need to spend your way out of it.
How to actually diagnose it properly
Microsoft gives you real tooling for this, and most teams do not use it. The plugin trace log, when switched on deliberately and temporarily, tells you exactly how long each step in your synchronous pipeline is taking. Browser developer tools show you every network call a form makes and how long each one takes to come back. The Power Platform admin centre gives you API call analytics broken down by app, user and operation, which is invaluable for spotting a badly behaved integration.
Use these tools before you guess. Guessing at Dynamics 365 performance problems wastes time and often leads people to blame the platform itself, when the platform is doing exactly what it was told to do by customisations built up over years without anyone stepping back to review them.
If you are dealing with a system that has slowly ground to a halt over a few years of well meaning customisation, you are not alone, and it is very rarely a lost cause. Most of the fixes above take days, not months. The hard part is usually just making the time to properly look, rather than living with a system everyone has quietly learned to tolerate.


