When to Hire a Dynamics 365 Consultant vs. DIY Implementation
A decision guide for teams asking whether their Dynamics 365 or Power Platform project really needs a developer, and which parts of it do. It ends with a downloadable pre-implementation checklist for the weeks after you decide.
Can you really implement Dynamics 365 or the Power Platform without a developer? For a large part of a first rollout, yes. Forms, views, business rules, business process flows, dashboards, security roles, and most Power Automate cloud flows are configuration a capable maker can own. Expert help becomes necessary at predictable walls: pricing rules the price list cannot express, SLA behaviour beyond status and calendar, migration that preserves relationships and history, real record volumes, integrations with their own authentication, and separated environments. This guide names those walls, then settles whether what you build belongs inside Dynamics 365 or in a separate Power App. Solzet is a Dynamics 365 and Power Platform consultancy in Yerevan, Armenia.
Two notes before the detail. First, we sell exactly the thing this page is asking you to consider buying, so the test we hold ourselves to below is that every wall is a documented platform behaviour you can verify yourself rather than a scare story. Where the do it yourself route is genuinely the right one, the page says so. Second, we publish no benchmark statistics and no success rate percentages here, because we cannot evidence them for your project. The two places this page does give numbers are the licence comparison in the extend against build section, where Microsoft list pricing is quoted as an order of size you should verify against the current price list rather than as a figure to budget from, and the budgeting section for the Caucasus region, where effort ranges are stated as planning ranges from the work we scope in this market and supplier cost is compared by relative tier, with no published hourly rates, not as a price list and not as a quote for you. Use them to build a budget you can defend internally, then hold them against two or three real proposals. Platform limits and configuration surfaces are Microsoft behaviour and Microsoft revises them, so check the current documentation before you build a plan on any single one of them.
Should you build it yourself or hire a Dynamics 365 consultant?
Build it yourself when
The process you are automating is close to how the standard apps already work, the record volumes are ordinary, the data you are bringing in is small and clean, nothing outside Microsoft has to be integrated in a bespoke way, and being wrong is cheap to redo. This describes a great many first Power Platform builds, and a maker with time and a sandbox will beat waiting three weeks for a proposal.
Hire expert help when
You have hit one of the walls below and the workaround is starting to look like a second system: pricing rules the price list cannot express, SLA conditions beyond status and business hours, a migration carrying relationships and history, volumes that make canvas queries misbehave, an integration that needs its own authentication and retry logic, or a production environment with no separation and no managed solutions. Also hire when the build is now business critical and one person holds all of it in their head.
Either way, settle this first
Who owns this in year two, and where does it run. Most builds we are asked to rescue were not badly made. They were made in one environment, in the default solution, by one person who has since changed roles, and nobody decided any of that. Those two answers cost nothing to write down at the start and are expensive to reconstruct later.
Which Dynamics 365 work should stay in-house, by task type?
Draw the line by the kind of work, not by budget. Configuration, view and form edits, simple business rules and most reporting belong with your own team once someone is trained. Plug-in development, solution architecture, Dataverse security redesign, ALM pipelines, data migration and anything touching a production cutover do not, because a mistake there lands in production and is expensive to reverse. Most teams end up with both columns of this table in the same project.
| Task | Who should own it | Why |
|---|---|---|
| Configuration: tables, columns, choices and relationships inside an agreed data model | In-house, once trained | Maker portal work that is quick to change and quick to undo in a development environment. The data model itself deserves a review before the first records exist, but the everyday additions to it do not need a supplier. |
| Views and form edits | In-house, once trained | The people who use the screens know what belongs on them, and a trained admin can change a view or a form section in minutes. Routing these through a supplier makes every small request a purchase. |
| Simple business rules | In-house, once trained | Show and hide, required levels, default values and field validation on one row are exactly what business rules were designed for, and they are solution aware and easy to remove. |
| Most reporting: views, charts, dashboards and Power BI over well modelled data | In-house, once trained | Reporting changes constantly and belongs close to the questions being asked. Bring in help for the model underneath when numbers start to disagree, not for each new chart. |
| Plug-in development | A delivery team | Compiled code running inside the save transaction in production. It needs source control, a test environment, code review and someone who understands pipeline stages, and a mistake affects every record written through that message. |
| Solution architecture | A delivery team | Deciding what is configuration, what is code, what extends Dynamics 365 and what sits beside it. These decisions are cheap in week one and expensive to reverse after a year of records, which is when an in-house team usually meets them for the first time. |
| Dataverse security redesign | A delivery team | Business units, team ownership, hierarchy and field level security change who can see existing records, and moving ownership moves rows rather than permissions. It needs a design, a rehearsal and a rollback, not an afternoon in the admin centre. |
| ALM pipelines | A delivery team | Separate environments, managed solutions, source control and automated deployment are set up once and then used by everyone. Getting the foundation wrong is the most expensive wall on this page, so it is worth having it built by people who have built it before. |
| Data migration | A delivery team | Dependency order, alternate keys, duplicate matching, preserved history, throttling and reconciliation. It is a workstream with its own rehearsal, and it is the line item most often underestimated. |
| Anything touching a production cutover | A delivery team | A cutover needs a runbook, a rollback, a freeze and named people accountable on the night and through hypercare. Your team should be in the room for it, but it should not be the first cutover anyone involved has run. |
Trained is doing real work in that sentence. An in-house owner needs a development environment, a named solution to work in and a clear route to production, which is the foundation the right hand rows put in place. The eight walls further down this page are the detail behind those rows.
Why do freelancer marketplaces fail for Customer Engagement work?
Not because the people on them lack ability. Many are capable engineers, and for a small, self contained task that someone in-house can review, a marketplace hire can be the right call. Implementation work on Dynamics 365 Customer Engagement fails there for reasons built into the arrangement.
No continuity
The contract is with one person. If they take a longer contract, fall ill or simply stop replying, the knowledge of your environment leaves with them and the search starts again. Customer Engagement builds depend on context that is not visible from the screens: why a plug-in step is registered where it is, which flow owns which update, which layer is holding a form together.
No source control handover
Marketplace work is usually accepted on the result on screen. What is often never delivered is the thing you need in year two: plug-in source in a repository you own, unmanaged solutions exported and versioned, connection references rather than personal connections, and notes good enough for the next developer. Without them the next person starts by reverse engineering your system.
No accountability at cutover
A milestone is marked complete when the work is accepted in a sandbox. The failures that matter happen at go-live: the migration that throttles, the security role that hides records, the integration that duplicates on retry. A single contractor paid per milestone has no obligation to be there at eleven at night or during hypercare, and no colleague to call if they are not.
What a delivery team provides instead
Named people who have delivered on this stack, and a second senior person who reviews the work and knows your environment well enough to cover absence.
Work in your repository and your environments from the first day, with managed solutions and a deployment route, so the handover is continuous rather than a final event.
A cutover runbook with a rollback, owned by the same team through go-live and hypercare.
A contract with a company that carries the obligation, rather than with an individual whose availability is the whole of the arrangement.
Freelancers, recruiters, generic agencies and a senior consultancy are compared on time to productive work and continuity, together with the questions to vet any of them in one call, on our page on Dynamics 365 staff augmentation and subcontracting.
Short engagement or ongoing retainer
Once you know which rows of the table need a delivery team, the shape of the engagement follows from the shape of the work.
A short engagement fits when
- The work has a defined end state you can write down: a migration, an ALM pipeline, a security redesign, a plug-in, a cutover.
- Acceptance can be tested, so both sides know when it is finished.
- Your own team will own the result afterwards, and knowledge transfer is written into the scope.
- Once the work is done, the rest of the backlog is configuration from the left hand side of the table above.
An ongoing retainer fits when
- A steady flow of engineering grade changes arrives every month: plug-ins, integrations, code components, data fixes.
- Release waves, integrations and scheduled jobs need someone watching and regression testing on a schedule.
- Nobody in-house can review compiled code or own the deployment pipeline.
- The system is business critical and you need a known response path when something breaks, rather than a new search each time.
What can you genuinely build without a developer?
Worth being precise about, because the honest answer to the question in the title starts here. This is real, supported maker surface, and a team that uses it well needs far less custom development than it expects.
The data model and the apps on top of it
Tables, columns, relationships, choice sets, forms, views, charts, and dashboards are all designed in the maker portal. A model driven app is generated from that model rather than laid out by hand, which is exactly why a functional consultant or a strong business analyst can produce a working Sales or Customer Service app without a developer anywhere near it.
Rules that live on the form and on the table
Business rules set values, set requirement levels, show and hide fields, and validate input without code. Scoped to a form they can drive visibility; scoped to the table they apply wherever the record is written, with a narrower set of actions. For most field level logic this is the correct tool, and reaching for JavaScript before trying it is one of the more common self inflicted maintenance costs we find.
Process guidance and stages
Business process flows put a visible stage bar on the record and can require fields before a user moves on. They are configuration, they are solution aware, and they cover the majority of "make people follow the process" requirements without anything custom.
Automation with Power Automate
Cloud flows triggered by a Dataverse row change, a schedule, an approval, or an email cover a very large share of real automation. Approvals, notifications, document generation, and pushing a record into another Microsoft 365 service are all first party connector work. Classic workflows are the previous generation of this and new automation belongs in Power Automate.
The standard modules, properly configured
Sales has price lists, discount lists, quotes, orders, forecasting, and goal management. Customer Service has queues, routing, entitlements, knowledge, and service level agreements. Field Service has work orders, bookings, and a schedule board. A great deal of what buyers assume is custom development is a standard module nobody switched on or nobody configured past the demo.
Reporting and analysis
Views, charts, and dashboards inside the app, and Power BI on top of Dataverse for anything wider. Because the data sits in Dataverse rather than in a product silo, reporting across sales, service, and the rest of the business does not require an export layer somebody has to maintain.
A related trap sits on the other side of this list: assuming a requirement needs custom work when a standard module already covers it. Our guide to the customization mistakes we see most often covers the code that should never have been written in the first place.
Where are the eight walls where no code runs out?
Each one states what the platform gives you, where it stops, and what crossing it costs. If none of these describe your project, you probably do not need us yet. If two or three do, the question has already changed from whether to hire help to how much.
1. Pricing and discounts the price list cannot express
Dynamics 365 Sales gives you real pricing configuration: price lists per currency and per customer segment, price list items with pricing methods based on a currency amount, a percentage of list, or a markup or margin on cost, rounding rules, and discount lists that apply an amount or a percentage across quantity bands. That covers standard commercial models and it covers them without code. It stops when the price depends on something the price list does not know: a negotiated agreement per customer with its own validity dates, bundle logic where the discount depends on what else is on the quote, tiered rules that compound, a margin floor that has to block a save, or a rate imported from another system at the moment of quoting.
What crossing it costs. Sales exposes this deliberately. You can turn the system pricing calculation off in the Sales settings and register a plug-in that responds to the pricing messages, so your own code returns the price for a quote, order, and invoice line. That extension point exists precisely because configuration cannot express every commercial model. It is also the point where you now own compiled code in a production environment, with the testing, source control, and deployment that implies. This is the single most common reason a DIY Sales build ends up needing a developer.
2. SLA rules beyond status and business hours
Service level agreements in Customer Service are configuration too, and quite deep configuration. Enhanced SLA items carry applicable when, success, pause, and warning and failure conditions, each with its own KPI, and the clock can be measured against a customer service schedule so it does not run outside working hours. Pause behaviour is driven from case statuses nominated in the service configuration settings. It stops when the clock has to obey something that is not a status and not a calendar: a different clock per contract or per region, a pause that depends on who you are waiting for rather than what the status says, an escalation chain with its own approval, or a KPI that has to survive a case being reassigned between teams with different hours.
What crossing it costs. The usual crossing is a Power Automate flow or a plug-in that writes the status or an SLA related field on the case, and it is worth knowing that these are also the two most common causes of SLA timers that appear to pause at random. Our guide to fixing SLA timer pauses walks through diagnosing exactly that, and it is a good illustration of the wider point: the automation somebody added to work around a configuration limit becomes the thing the next person has to debug.
3. Migration that has to keep relationships and history
Bringing data in is where most DIY implementations first discover they are past the line, because the easy path works right up until it does not. The import wizard and an Excel template are genuinely fine for reference data and small lists. They stop at the point where rows have to resolve lookups to records that do not exist yet, where the same record arrives twice from two sources and has to be matched rather than duplicated, where created on dates and record ownership have to be preserved so the history means anything, where notes and attachments have to come across as files, and where the row count is high enough that per row logic and platform throttling become the constraint rather than the file size.
What crossing it costs. The competent version of this is a staged migration: clean and key the data outside the platform, load in dependency order using alternate keys on source identifiers, disable the per row logic while loading, write in bulk rather than one row per request, and reconcile before switching automation back on. That is a workstream with its own plan and its own rehearsal, not a task somebody does on the Friday before go live. Two pages on this site go through it in detail, one for a Salesforce source and one for volume in general.
4. Volume the app was never tested against
This one is invisible in a demo and obvious in production. Canvas apps delegate what they can to Dataverse, and everything they cannot delegate is evaluated only against the rows they have already pulled back, which is a few hundred by default and capped in the low thousands even when you raise the setting. A filter or a lookup written the wrong way against a large table therefore returns an answer that is wrong rather than slow, and it is right during testing because the test data was small. Model driven views, plug-ins written without regard for query cost, and flows that loop row by row have their own versions of the same surprise.
What crossing it costs. The fix is usually design rather than code: delegable queries, filtering at the source, aggregation done in Dataverse or in Power BI, and testing at realistic volume before anybody trusts a number on a screen. Where the requirement genuinely cannot be delegated, the answer is a proper server side component rather than a bigger row limit. Knowing which of those two situations you are in is the expertise being bought.
5. Integrations with their own authentication and failure modes
The connector library covers an enormous amount, and if the other system has a maintained connector then a maker can integrate it. It stops when the other side needs a client credentials flow you have to configure, a custom pagination or batching scheme, a webhook you have to receive and authenticate, ordering guarantees, or idempotency so that a retry does not create a duplicate record. It also stops at error handling: a flow that has never been given a retry policy or configured run after behaviour looks fine for months and then silently drops the record that mattered.
What crossing it costs. Custom connectors, Azure Functions, service principals, and plug-ins registered on the right message in the right stage. This is ordinary engineering, but it is engineering, and the part that most often gets skipped is not the happy path. It is what happens on the second attempt, on a partial failure, and at three in the morning when nobody is watching.
6. One environment, unmanaged, with no way back
This is the wall that costs the most and the one that looks like nothing at the time. Application lifecycle management on the Power Platform means separate development, test, and production environments, changes made in a named unmanaged solution rather than in the default one, and deployment into production as a managed solution so layers behave predictably and a component can actually be removed again. A DIY build almost always starts as the opposite: one production environment, everything in the default solution, changes made live.
What crossing it costs. Unwinding it later is real work: identifying what was customized, separating it into solutions, standing up the other environments, and moving to managed deployment without breaking what users depend on. Nothing about this is dramatic on any given day, which is exactly why it is left, and it is the reason a build that worked perfectly well for a year becomes unmaintainable in its second year.
7. A security model designed after the fact
Security roles are configuration, and for a single team with one way of working they are simple. The design questions arrive with the second team: business units and how ownership maps to them, teams as owners rather than individuals, sharing, hierarchy security for managers, and field level security for the handful of columns not everyone should read. The model is straightforward to design at the start and disruptive to change later, because ownership and business unit changes move records rather than just permissions.
What crossing it costs. There is no code required here, which is what makes it a different kind of wall. What is required is somebody who has seen the model fail before and asks the awkward questions in week one, when the answer is a design decision rather than a migration.
8. Interface behaviour the form designer does not have
Most requests to make a screen behave differently are met by the standard designers, and should be. What the designers do not give you is a genuinely different component: a board a user drags cards across, a chart from a specific library, a scheduler, a map, an editable grid with rules of its own, or a rich viewer for data that arrives as raw text. Those are code components built with the PowerApps Component Framework in TypeScript, packaged into a solution and imported like any other component.
What crossing it costs. A code component is the clean way to cross this line, because it is a supported, packaged, versioned artefact rather than script layered onto a form. The tempting alternative, JavaScript pasted onto form events with no repository behind it, is the version we most often meet during a rescue, and by then nobody can say what it does or whether it is safe to remove.
The first wall, pricing, is worked all the way through further down this page. See implementing volume based discounts without code for the three configuration routes, the point each one stops, and when the answer becomes a code component or a configure price quote product.
Three of those walls have full guides on this site. For service level agreements, see why SLA timers appear to pause at random and how to fix it. For migration, see the Salesforce to Dynamics 365 data migration guide and, for volume specifically, importing millions of rows into Dataverse.
For custom interface components, the PCF controls development service page explains what a code component is, and team versus freelancer for PCF work is the buying decision one level down from this page.
How do you implement volume-based discounts without code?
The first wall above is pricing, and it is the one readers of this page write to us about most, so it gets worked all the way through rather than left as a warning. Tiered discounts are the classic case where a maker is told it needs a developer far earlier than it does. A useful amount of it is configuration, and the three routes below are written so you can follow them in a sandbox this afternoon: business rules on the quote line, a Power Automate flow over a tier table, and our free String Calculator control for making the resulting number explainable. Then the honest part, which is the exact point each one stops and what it costs to go past it.
Do the catalogue first. All three methods sit on top of a correct Dynamics 365 Sales catalogue, meaning unit groups, a price list per currency, price list items with the right pricing method and rounding, and the native discount lists wherever plain quantity bands per product already express the rule. A great deal of what arrives described as complex pricing turns out to be expressible there, and every route below still needs that layer underneath it. Our guide to volume discounts and complex pricing in Dynamics 365 Sales sets out those objects, the ten places the native discount list runs out, and the server side options with worked code. This section is the no code half of that decision and does not repeat it.
Which method fits which requirement
Find the row that describes your rule and read across. Choosing the wrong layer costs far more than implementing the right one badly, because the wrong layer is discovered by a customer rather than by a tester.
| The requirement | Business rules | Power Automate flow | Code component or plug-in |
|---|---|---|---|
| Simple two tier. One product or a short list, quantity bands on a single line, rates that change once a year, no dates and no customer specific terms. | Yes, and this is the right answer. One table scoped rule, two branches, an afternoon of work, nothing to deploy and nothing to retest at a release wave. | Overkill. You would be adding a table, a trigger loop guard, and an asynchronous window to express two thresholds that fit in a designer. | No. Writing a plug-in for a two tier quantity discount is the over-customizing this whole page is trying to prevent. |
| Complex multi tier. Several bands, tiers measured on order value rather than count, the same product across several lines that has to be added together, promotions with start and end dates, a different scheme per customer agreement. | No, and not close. There is no aggregation across lines, no lookup into a tier table, and no date range handling, so any attempt becomes a wall of branches that is wrong the first time commercial terms change. | Yes, provided the number is allowed to settle a few seconds after the save. Tiers live as rows in a Discount Tier table, the flow aggregates the siblings and applies the match, and a commercial manager maintains the scheme without a developer. | Only when the discount must also be correct for rows arriving from an import or an integration, or when a margin floor has to block the save. That is a synchronous plug-in and it is developer work. |
| Real time quote calculation. The seller has to see the tier and the resulting price change as the quantity is typed, before saving, and expects a what if answer while negotiating on a call. | Partially. A formula action updates on the form as columns change, so a single line calculation can feel live, but nothing that depends on the other lines can be shown this way. | No. Asynchronous by design, so the number arrives after the save. Keep the flow for the approval routing and the nightly audit that sit around the calculation. | Yes, and this is the honest trigger for a custom control. A PCF control on the line or the grid can read the sibling lines and the tier table through the Web API and show the tier live, paired with a plug-in that enforces the same rule server side. |
| Everything past that. Configurable products with compatibility rules, bundles and kits priced as a unit, guided selling, subscription ramps and proration, renewal uplifts, and a multi level approval matrix over the discount. | No. | Only for the approval matrix and the notifications around it, which it does well. | This is where building stops being the cheaper option. Evaluate a configure price quote product on AppSource against a build, using the test in the paragraph below the table. |
One reading rule for that table. The column that matters is not the cleverest option available to you, it is the cheapest one that still makes the number true for every way a row can arrive: a seller on a form, an import file, an integration, and a flow. A method that is right on the form and wrong on the import has not solved pricing, it has moved the error somewhere nobody is looking.
The three no code methods, configured step by step
Each block below is what we would actually click, in order, in a development environment. Column names are the ones you will see in the maker portal, so they can be searched for once you leave this page.
Method 1. Business rules on the quote line
A business rule is the only one of the three that runs inside the save, which is what makes it the right first attempt. Scoped to the table rather than to a form, it applies wherever the row is written, including from an import or an integration, and it costs nothing to remove. Its reach is narrow and precise: conditions read columns on the row being saved, and the set field value action can write a value, another column, or a formula built from the numeric and currency columns on that same row.
Open your unmanaged solution in the maker portal, add the Quote Line table, and choose Business rules, then New business rule. Do this in a development environment, never in production, because a rule that writes a currency column is a pricing change.
Set Scope to Entity in the rule designer, not to a single form. Form scope only runs while somebody has the form open, so a line created by a bulk import or by a flow would silently keep a zero discount.
Add a condition on the Quantity column, greater than or equal to your first threshold, for example 100. Add the product condition alongside it if the tier only applies to part of the catalogue, since a business rule has no way to look a product up in a tier table.
On the true branch, add a Set Field Value action targeting Manual Discount Amount, switch the value type to Formula, and enter Quantity multiplied by Price Per Unit multiplied by your rate, for example 0.05 for five percent. Currency and numeric columns on the same row are the only inputs a formula accepts.
Add the second tier as a further condition branch with its own threshold and its own rate, and set the discount back to zero on the else branch so a line edited downwards is corrected rather than left holding the old number.
Activate the rule, then test three ways before you trust it: a line typed on the form, a line created by an import file, and a line whose quantity is edited downwards after saving. Also press Recalculate on the quote header and confirm the number you wrote survives it, because the pricing engine reprices lines when the header changes.
Where it stops. It stops at one row. A business rule cannot see the other lines on the quote, cannot total them, cannot read a tier from a configuration table, and cannot compare against a date range without a date column on the line itself. It also has no loop, so every band and every product family is another branch drawn by hand, and past roughly two tiers on a handful of products the rule becomes the thing nobody dares edit. If your tiers are quantity bands on a single line and there are two or three of them, stop here and keep the money.
Method 2. A Power Automate flow over a tier table
This is the route that buys you everything a business rule cannot reach: the order total, several lines of the same product added together, tiers held as data rather than as branches, validity dates, and a different scheme per customer agreement. The rules stop being drawn in a designer and become rows in a table that a commercial manager can edit without opening a solution.
Build the tier table first. One custom Dataverse table, Discount Tier, with columns for product or product family, price list, threshold from, threshold to, whether the threshold is a quantity or a value, the percentage, valid from, valid to, and the customer segment or agreement it belongs to. Every rule your commercial team can describe should fit as a row, and any rule that does not fit is the signal to re-read the escalation guidance below.
Create an automated cloud flow with the Dataverse trigger When a row is added, modified or deleted, table Quote Lines, scope Organization. Fill in Select columns with quantity, price per unit, product and the parent quote, so an edit to an unrelated column does not start the flow.
Add a trigger condition that ignores updates made by the flow itself. The usual implementation is a Discount calculated on date column on the line that the flow stamps at the end of its run, with the trigger condition excluding rows the flow has just touched. Skip this and the flow retriggers itself until the platform loop protection turns it off, which is the single most common way this build fails in week one.
List rows on Quote Lines filtered by the parent quote to get every sibling line, then compute the aggregate the tier is measured on, whether that is total quantity across lines of the same product or the value of the whole quote. This is the step business rules cannot express and the reason this method exists.
List rows on Discount Tier filtered by product, by the aggregate falling between threshold from and threshold to, and by todays date sitting inside valid from and valid to, sorted so the best matching row comes first, with row count set to one. Handle the empty result explicitly rather than letting a null reach the update.
Update each line with the resulting Manual Discount Amount and stamp the calculated on date. Wrap the external steps in a scope with a configured run after path so a failure lands somewhere a person looks, and add a scheduled flow that reruns the calculation nightly across open quotes and reports any line whose discount does not match the scheme that should have produced it.
Where it stops. It stops at the guarantee. A flow is asynchronous, so between the moment a seller saves a line and the moment the number is correct there is a window of seconds, and nothing prevents a quote being emailed inside that window. It cannot block a save, so it cannot enforce a margin floor, and two lines edited at once can produce a race that leaves one of them holding a stale figure. Use it for schemes that are allowed to settle a few seconds later, for the approval routing around a discount, and for the nightly audit. Where the number has to be right at the instant of the save no matter how the row arrived, that requirement belongs in server side code, and the volume discounts guide linked below sets out exactly how.
Method 3. The Solzet String Calculator control, for making the discount legible
Worth being straight about what this one is, because the name invites a wrong assumption. Our String Calculator is a free code component that turns a single line of text column into a composer: you tell it which columns to pull from and which separator to use, and it keeps that text up to date on the form with no JavaScript anywhere. It does not compute a tier and it is not a pricing engine. What it solves is the question that follows every automated discount, which is why is this line twelve percent off, and it solves it without anybody writing form script.
Download the managed solution from the control page and import it into your development environment, then move it forward through your normal solution route like any other component.
Add a single line of text column to Quote Line, named something like Discount basis, and add it to the form. This column holds an explanation, so it should be read only to sellers.
On the form designer, select the column, open Components, add the String Calculator, and set it for web, tablet and phone so the explanation travels with the record rather than only appearing on a desktop.
Configure the control parameters with the columns that explain the number: the tier label, the percentage applied, the agreement or price list it came from, and the calculated on date stamped by the flow in method two. Set the separator to whatever reads cleanly, and publish.
Test it against a line the flow has priced and a line it has not. An empty basis on a discounted line is a useful alarm, because it means a number arrived on that row without a scheme behind it.
Where it stops. It stops at display. It reads columns and composes text, so it is the transparency layer over whichever of the first two methods produced the figure, and it is genuinely valuable there: a discount an auditor can read on the record is worth more than one that only exists inside a flow run history. It is not a substitute for the calculation, and if what you actually need is a control that recalculates a tier while the seller is still typing the quantity, that is the custom control described below rather than this one.
The control in method three is free and downloadable from its own page, with a demo of what it does on a form: see the Solzet String Calculator. The flow in method two is ordinary cloud flow work of the kind covered by our Power Automate consulting service, including the error handling and the scheduled audit that most first attempts leave out.
When to escalate to a custom control or a CPQ product
Four signals, each with what it actually means you should build. If none of them is true for your scheme, the two configuration methods above are the whole answer and you do not need us for this.
The discount has to be visibly correct before the record is saved, and it depends on more than the line being typed.
A custom code component, built with the PowerApps Component Framework, on the line or on the editable grid. It reads the sibling lines and the tier configuration through the Dataverse Web API and updates as the user types, which is the one thing neither a business rule nor a flow can do. Always pair it with server side enforcement, because anything running in a browser is bypassed by an import, and a control alone gives you a good demonstration rather than a correct database.
A margin floor, a discount ceiling, or an authorisation threshold has to stop somebody rather than warn them.
A synchronous plug-in registered on the line and the header. This is the wall described first in the eight above, and it is the point where a Sales build acquires compiled code, source control and a deployment route. Power Automate handles the approval that follows the block, but it cannot be the block itself.
Commercial terms change faster than a developer can deploy, and the people who own them are in sales rather than in IT.
Keep the engine in code and move the terms into data. A tier table maintained by the commercial team, read by the plug-in and by the flow alike, means a new promotion is a row rather than a release. This is the single design decision that most often decides whether a pricing build is still in use in year three.
Products are configured rather than picked, bundles have their own pricing, quotes carry subscription ramps and renewal uplifts, or the approval matrix has several levels with different thresholds.
Stop building and evaluate a configure price quote product from AppSource against the cost of the build. The test we apply is simple: if the way you price is a competitive advantage that no vendor models, build it and own it. If it is complexity you inherited and would rather not maintain, buy the product and spend the budget on the integration instead. We give this answer against our own interest often enough that it is worth writing down.
Where that lands on a real time control, the build is a code component in TypeScript, packaged into a solution and versioned like anything else, which is our PCF controls development work. Where it lands on the plug-in that enforces the rule server side, that is Dynamics 365 development, and it is usually a small, well bounded piece of work rather than a project. The sequence we recommend to clients is the same one this section is written in: configure what configuration reaches, automate what is allowed to settle a second later, and buy code only for the rule that has to hold at the moment of the save.
How do you handle advanced pricing and discount scenarios?
The section above answers what a maker can build. This one answers the question that arrives once the answer is not enough, and it is the more expensive question, because it is no longer about whether to hire anybody. It is about which layer of the platform the calculation belongs in. Native discount lists, calculated columns, rollup columns, business rules, flows and plug-ins are each documented well and separately, and nothing in that documentation tells you which one your rule needs. Choosing wrong is not a performance problem. It produces a number that is confidently displayed and quietly incorrect, and it is normally found by a customer holding a quote rather than by a tester. Below: what the native pricing objects genuinely cannot express and what each limit forces on your design, a decision tree with one question per gate, short code for the three layers people get wrong, and the architecture decisions that determine whether the build survives its second year.
The short answer to how to calculate automatically on order volume. Put the order volume figure on the quote header as a rollup column, decide in one sentence how fresh that figure has to be, and let that sentence pick the layer. Up to an hour old is fine for tier visibility, approval routing and reporting, and that is pure configuration with nothing deployed. Correct within seconds of the save is a Power Automate flow over a tier table, which is the section above. Correct at the instant of the save, whatever wrote the row, is a synchronous plug-in and is the only one of the three that is developer work. Almost every argument we are asked to settle about volume pricing turns out to be that freshness question, unasked.
Where native discount lists and price list items stop
Four limits, and for each one the design decision it forces rather than just the behaviour. The pricing objects themselves, meaning unit groups, price lists, price list items and the transaction lines they write to, are set out on our volume discounts and complex pricing guide and are not repeated here. Read that first if you are not sure your catalogue is right, because every limit below assumes it already is.
The unit of evaluation is one line, and the only input is quantity
A discount list is attached to a price list item, so it is evaluated against a single transaction line, and its bands are quantity bands. It reads the quantity on the line in front of it. It cannot see the order total, it cannot add two lines of the same product together, and it cannot band on a currency value, so a rule worded as five percent once the order passes fifty thousand has no expression in the object at all. The nearest thing configuration offers is a discount typed on the quote header, which is a number a person enters rather than a scheme the system applies.
What it forces on your design. The order volume figure your tier is measured on does not exist anywhere in the native model, so the first design decision is not the tier logic. It is where that figure will live and how fresh it has to be. That is gate three below, and taking it second is why volume pricing builds get rewritten: the team builds the bands first and discovers afterwards that the number feeding them is an hour old.
There is no time dimension, and nothing reprices backwards
A discount list carries no valid from and no valid to. A quarterly promotion is therefore not a row you schedule, it is a manual edit somebody makes on the morning it starts and has to remember to undo on the evening it ends. Price list items have no dates either, so a price change is a new price list or an edit to the live one. And pricing is evaluated when the line is written rather than continuously, so lines sitting on open quotes keep the numbers they were given until something reprices them.
What it forces on your design. Two things follow. Validity has to be modelled by you, which in practice means a tier table with a from date, a to date and a scheme identifier. And there has to be a deliberate answer to what happens to quotes priced under the scheme that just expired. Silence on the second point is the defect your customer finds, because your customer is the one holding the old quote.
Precedence is single valued, and a manual price leaves the engine
One price list item carries one discount list, so discounts do not stack and there is no ordering rule to configure between a volume scheme and an agreement scheme. Whichever list is attached is the one that runs. Separately, a line whose price has been overridden opts out of the pricing calculation entirely, which is exactly what that flag is for, and it is correct behaviour right up until it is also the route by which a seller quietly steps outside the scheme.
What it forces on your design. If more than one scheme can reach the same product, precedence has to be decided before anything is built and it has to live in one place that every route reads. An override policy is a design decision rather than an oversight too: decide whether an overridden line is exempt from the scheme or still owes the margin floor, then enforce whichever you chose. Both routes below can honour either answer, and neither can guess it.
The engine prices, it does not police
There is no margin floor in the pricing objects, no authorisation threshold, no ceiling on a manual discount, and no record of which scheme produced a number. Write-in products, meaning lines typed as free text rather than picked from the catalogue, sit outside the price list altogether and take whatever price and discount the seller enters on them.
What it forces on your design. Every control anybody asks for around a discount has to be built on top: the floor, the approval, the audit trail, and the answer to why is this line twelve percent off. None of it is a configuration gap you can close where the pricing lives, and recognising that is usually the moment a pricing requirement is correctly reclassified from configuration work to development work.
The decision tree: calculated column, rollup, business rule, flow, or plug-in
Answer the gates in order and stop at the first yes. Each gate is a single question, and the no branch tells you what to carry into the next one, because the part of your rule that fails a gate is the part that decides the cost of the whole thing.
Gate 1
Can the rule be stated as quantity bands on a product, with no dates, no order level total and no customer specific terms?
Yes. Native discount list on the price list item, and stop here. It runs inside the pricing engine, so it applies however the row arrives, there is nothing to deploy, and there is nothing of yours to retest at a release wave. Anyone selling you code for this is selling you a maintenance liability.
No. Continue, and note which part of the rule failed, because everything below branches on exactly that: the input the band is measured on, how fresh the answer has to be, or whether something has to be stopped.
Gate 2
Is the value pure arithmetic over columns on the same line or on its parent quote, and does it only need to be read rather than to move the quote total?
Yes. A calculated column, which costs nothing and cannot go stale, because it is evaluated when the row is retrieved rather than stored. It can reach the parent record through the lookup on the line, so the tier label, the effective unit price, the achieved margin percentage and anything a view, a chart or an approval condition has to filter on all belong here rather than in a flow that writes them.
No. Continue, and be precise about why, because a calculated column fails here for two very different reasons. Either the arithmetic needs rows it cannot see, which is gate three. Or the result has to land in a writable pricing column, which no calculated column can do at any size: Manual Discount Amount is a system column and cannot be converted to a calculated one, and the pricing engine and the header totals ignore computed columns regardless. A calculated column can measure the discount. It cannot be the discount.
Gate 3
Do you need the order volume figure itself, meaning total quantity or total value across the lines of a quote, and can that figure be up to an hour old?
Yes. A rollup column on the quote header, with no code anywhere. This is the cheapest honest answer to how to calculate automatically on order volume, and for tier visibility on the header, approval routing, dashboards and the input to a nightly audit it is the right answer rather than a compromise. Recalculation runs on an asynchronous system job instead of inside the save, so treat the number as reporting grade and use the on demand refresh where a person needs it immediately.
No. Continue. If the figure has to be right at the instant of the save, a rollup column cannot supply it and no amount of configuration changes that, because the aggregate then has to be computed in the same transaction as the write. That is gate five. This is the most common place a volume pricing build is found to be wrong, and it is normally found by a seller who has already emailed the quote.
Gate 4
Does a writable pricing column have to be set automatically, and is the scheme allowed to settle a few seconds after the save?
Yes. A table scoped business rule if the whole calculation sits on the line, or a Power Automate flow over a tier table if it needs the sibling lines, the validity dates or the agreement. Both are configured step by step in the section above and neither needs a developer. Add the trigger guard and the nightly reconciliation while you are there, because those two omissions are the difference between this route working and this route being distrusted.
No. Continue, and the reason will be one of two sentences. The number has to be correct however the row arrived, including from an import file and from an integration. Or something has to be stopped rather than corrected afterwards. Both of those mean code, and neither of them means a big project.
Gate 5
Must the number be correct at the moment of the save whatever wrote the row, or must a floor or a threshold block the save rather than warn about it?
Yes. A synchronous plug-in, and this is the gate where you are hiring. Register pre-operation on the line for the calculation and pre-validation for the block, which is the shape of the two examples below. Be clear about what you are buying: not the plug-in, which is small, but the compiled code in a production environment and the source control, managed solution route and test environment that have to exist around it from then on.
No. You are not at this gate, so go back to gate four and take the configuration route. A plug-in written for a requirement gate four already covers is the over-customization our customization mistakes guide opens with, and it is billed to you twice: once to build, and again at every release wave for the rest of its life.
Gate 6
Is the price itself arriving from outside the catalogue, or has the requirement stopped being a discount rule and become a pricing system?
Yes. Two different answers, and the distinction matters commercially. Where the price for every line comes from somewhere else, that is full custom pricing through the pricing messages with the system calculation switched off, which is the largest surface area named anywhere on this page and is worked through with code on the volume discounts guide. Where the requirement is configurable products with compatibility rules, bundles priced as a unit, guided selling, subscription ramps and a multi level approval matrix, evaluate a configure price quote product from AppSource rather than building, using the test in the escalation block above.
No. Then gate five was your answer, and what you are commissioning is a bounded piece of work rather than a project. Hold on to that when you brief it out: a well scoped pricing plug-in over a tier table is usually days of development, and a supplier who quotes it as a phase has either misunderstood the requirement or is pricing the risk of not having read it.
The three layers people get wrong, in code
Short and deliberately incomplete: these are shapes rather than finished components, and the helper methods named in them are yours to write. The complete order level allocation plug-in, including how to split rounding residue across lines so the line discounts add up to the intended order discount exactly, is on the volume discounts guide.
First, the answer most teams never try. Gate three, done entirely in configuration: rollup for the order volume figure, calculated column for the tier it lands in, and the honest statement of what those two cannot do.
// Order volume, and the tier it lands in, with no code at all.
// Verify both definitions in a sandbox before you rely on them: computed
// column behaviour is Microsoft behaviour and Microsoft revises it.
// 1. The order volume figure. Rollup column on the quote header.
Table Quote (quote)
Column new_totalorderunits Decimal, Rollup
Aggregation SUM of Quote Line (quotedetail) . Quantity
Related Quote Lines, over the parental relationship to the header
Filter Quote Line . Price Overridden equals No
Refresh an asynchronous system job, hourly at the fastest, plus the on
demand refresh next to the column on the form. Never inside the
save, which is the one fact that decides whether you can use it.
// 2. The tier that figure falls into. Calculated column on the line.
Table Quote Line (quotedetail)
Column new_volumetier Whole number, Calculated
Condition Quote (Quote Line . Quote) . new_totalorderunits >= 500
Action new_volumetier = 3
One condition and action pair per band. The parent quote is
reachable because Quote is a lookup on the row being calculated.
// 3. The part neither of them can do, which is the part people assume.
// Both columns are computed and read only. The pricing engine does not consult
// them, the header totals do not move when they change, and Manual Discount
// Amount is a system column that cannot be redefined as calculated. So these
// two give you the measurement, the tier badge on the form, the view a manager
// filters, and the condition an approval reads. Something that can write still
// has to put the money in the writable column: a business rule, a flow, or the
// plug-in below. Calculated and rollup columns measure the discount. They are
// never the discount.Second, gate five. The calculation that has to be right at the moment of the save. Note the pre-operation registration: setting the value on Target rather than issuing a second Update is what removes the recursion problem instead of guarding against it, and it is the single detail that most separates a pricing plug-in that behaves from one that has to be turned off during data loads.
// Automatic calculation on order volume that is correct at the instant of the
// save, for a row arriving from a form, an import, or an integration alike.
// Register pre-operation on Create and Update of quotedetail, with an update
// filter on quantity, productid, uomid and priceperunit, and a pre-image.
public void Execute(IServiceProvider provider)
{
var context = (IPluginExecutionContext)provider
.GetService(typeof(IPluginExecutionContext));
var target = context.InputParameters["Target"] as Entity;
if (target == null) { return; }
var factory = (IOrganizationServiceFactory)provider
.GetService(typeof(IOrganizationServiceFactory));
var service = factory.CreateOrganizationService(context.UserId);
// Pre-operation on the row being written, so the value is set on Target
// rather than by a second Update. No extra write, no re-entry, and no
// recursion guard to get wrong later.
var quoteId = ResolveParentQuote(target, context, service);
if (quoteId == Guid.Empty) { return; }
// The aggregate has to include this row's new quantity, which is not yet
// in the database. Sum the siblings, then add the target.
var volume = SumSiblingUnits(service, quoteId, target.Id) + BaseUnits(target, context);
// Bands are rows in a Discount Tier table, matched on product, aggregate
// and today's date. They are never branches in this method.
var tier = _tiers.Match(service, quoteId, target, volume);
if (tier == null) { return; }
// priceperunit is absent from Target on a create the pricing engine has
// not reached yet, so fall back to the pre-image and then the price list.
var unitPrice = UnitPrice(target, context, service);
var quantity = Quantity(target, context);
target["new_schemediscountamount"] = new Money(
Round(quantity * unitPrice * tier.Rate, Precision(quoteId, service)));
target["new_appliedtierid"] = tier.ToEntityReference();
target["manualdiscountamount"] = new Money(
SchemeAmount(target) + SellerDiscount(target, context));
// The sibling lines were priced against a smaller volume and are now wrong.
// That is a separate registration on the set, not a loop inside this one.
// Queue it post-operation and reprice the whole quote in one pass.
}Third, the enforcement half of gate five, which is a different registration and a different intent. This is the one requirement on this page that no amount of configuration and no flow can meet, because only synchronous server side code can refuse a save.
// The rule a flow structurally cannot enforce: a discount that has to stop
// somebody rather than correct them afterwards. Register synchronously,
// pre-validation on Create and Update of quotedetail.
var floor = _tiers.MarginFloorFor(service, quoteId); // configuration, not a constant
var net = quantity * unitPrice - discount;
var cost = StandardCost(service, productId);
if (net < cost * (1m + floor))
{
throw new InvalidPluginExecutionException(
"This discount leaves the line below the margin floor for this agreement. "
+ "Request approval on the quote before applying it.");
}
// Pre-validation runs before the database transaction opens, so nothing is
// half written and the message reaches a seller on the form and the caller of
// an import or an integration in the same words. That is the whole reason the
// floor lives here rather than in a flow, which can only complain about a
// number that has already been saved and possibly already been sent.Architecture recommendations that decide year two
The gates decide the layer. These decide whether the thing is still trusted after the first commercial change, the first data load and the first person leaving. Each one is a mistake we have been paid to undo.
Tiers are data, code is only the engine
One custom Discount Tier table: product or family, price list, threshold from, threshold to, whether the threshold is a quantity or a value, the rate, valid from, valid to, and the agreement or segment it belongs to. The plug-in, the flow and the reporting all read the same rows, so a new promotion is a row a commercial manager adds rather than a release a developer deploys. Commercial terms change faster than deployments do, and a build where every band is a branch in compiled code fails on its first commercial change rather than on its first technical one.
Decide the repricing set before you write anything
A volume tier is a property of the set rather than of the row, so the moment one line changes, every other line on that quote may belong in a different band. Write down which lines get repriced, meaning the whole quote, the lines of the same product, or the lines under one agreement, and write down what happens to a line somebody has overridden. Skipping this produces the most confusing class of pricing bug there is: a quote whose lines are each individually explainable and collectively wrong.
Write the scheme discount to a column you own
Keep the automatic amount in your own currency column and let one place add it to any discretionary discount before the total reaches Manual Discount Amount. Two things follow, both worth an extra column. You can tell at a glance whether a number came from the scheme or from a person. And a rerun of the calculation cannot silently eat a discount somebody was authorised to give, which is the failure that ends trust in an automatic pricing build faster than an outage does.
Register the smallest plug-in that can work
Filtering attributes on the update step so editing a description does not reprice a quote. A pre-image instead of a retrieve. One query for the set instead of a query per line. No service calls inside a loop. A pre-operation mutation, or failing that a depth check, so the step cannot re-enter itself. Poor plug-in design is the second entry on our customization mistakes guide, and pricing is where we find the worst of it, because a pricing plug-in fires on the busiest table in the system and every inefficiency is multiplied by the line count of every quote in the business.
Stamp the answer, not just the number
Every automatically applied discount should carry the identifier of the scheme that produced it and the moment it was applied. Two columns. It makes the discount auditable on the record rather than only inside a flow run history, it gives a nightly job something to reconcile against, and it turns the question of why this line is twelve percent off into a field somebody can read instead of an investigation somebody has to run. Finance treats a discount nobody can explain as an error whether or not it was one.
Two of those recommendations are really the same warning from opposite directions, and it is worth naming it plainly: the expensive failure in pricing work is not a plug-in that is too small, it is a plug-in written where gate four would have done, registered on everything, containing the bands as branches. That is over-customizing a feature the platform already gives you, and it sits alongside the other patterns in our guide to the customization mistakes we are most often called in to fix, which also covers the plug-in registration and solution layering habits that keep the code at gate five maintainable once it does exist. Where the answer genuinely is gate five or gate six, the build is server side work on Dataverse, meaning a C# plug-in over a tier table, source control, a managed solution route and a test environment, and that is our Dynamics 365 development work. We are equally happy to be hired for a review of the tier model before anybody writes it, which is normally the cheaper half of the engagement and the half that changes the outcome. If your rule stopped at gate one, two or three, you have the whole answer above and you do not need us for it.
Should you extend Dynamics 365 or build a separate Power App?
The walls above tell you whether a requirement needs a developer. This section answers the question that arrives immediately afterwards and is decided badly far more often: does the thing you are about to build belong inside Dynamics 365, or does it belong in a separate Power App on its own tables. Microsoft documentation answers this from the product side, which is accurate and incomplete, because the decision is not really about what the tools can do. Both can do almost anything. It is about which licence the users need, what a release wave can move underneath you, and who owns the result in year two.
The one fact that settles most of these arguments. A Power Apps licence entitles a user to standard Dataverse tables and to the tables you create yourself. It does not entitle them to the restricted tables that belong to a Dynamics 365 application, and how the screen was built makes no difference to that. Every plan that begins with building our own app to avoid the licences ends at this line, whether the app is canvas, model driven, or a portal. Settle it in week one, not at renewal.
Which side of the line is your requirement on
Find the row that describes what you are actually building rather than what it was called in the meeting. Most requirements match one row cleanly, and the ones that match two are usually two requirements.
| What you are actually building | Where it belongs | Why, and what getting it wrong costs |
|---|---|---|
| Adding fields, rules, or a stage to a process that already lives on an account, a contact, an opportunity, a case, or a work order | Extend Dynamics 365 | The record, its security model, its service level agreements, and its reporting already exist. A separate app has to reproduce all four and the users hold a licence that already covers the record, so the parallel build buys nothing and costs a data model. This is the row most often got wrong in the other direction, by teams who were told a canvas app would be quicker. |
| A new internal process with its own records that the sales and service teams never touch: asset requests, site inspections, supplier onboarding, a fleet log, a safety checklist | A separate Power App, on your own tables, in the same environment | Nothing here is a Dynamics 365 record, so occasional users can be licensed per app rather than per application, and the release cadence is yours. Keep it in the same Dataverse environment anyway, so it can look up the real account record instead of a copy of the customer list. |
| A task focused or mobile screen for people who already work cases, opportunities, or work orders | Extend, with a canvas app or a custom page embedded in the model driven app | The Dynamics 365 record stays the single source of truth and the users work under the licence they already hold. Building this standalone is the usual route to a second copy of the customer list and a synchronisation job that nobody owns by year two. |
| A screen for people outside your organization: customers, applicants, partners, suppliers | Neither. Power Pages | External users are licensed by authenticated and anonymous page views rather than as internal users, so putting them into a Dynamics 365 app or an internal Power App is both the wrong experience and the wrong licence. This one is usually decided by accident and discovered at renewal. |
| A different interaction on a form that otherwise works: a board to drag records across, a map, a scheduler, an editable grid, a viewer for data that arrives as raw text | Extend, with a PCF code component | What you need is a control, not an application. Building an app around it to get one screen right leaves you maintaining an app forever. Wall eight above covers what a code component is and what crossing that line costs. |
| A departmental app over data that has nothing to do with the customer record, typically sitting in SharePoint, Excel, or a line of business database | A separate Power App | There is no benefit in it sharing a solution, a support rota, or a data loss prevention boundary with the CRM. Keeping it out is what stops the CRM environment quietly becoming the place where every app in the company ends up. |
| An app that reads or writes cases, opportunities, quotes, orders, or work orders, for people who do not hold a Dynamics 365 licence | The trap row. Either licence them, or change the design | Those are restricted tables. A Power Apps licence does not entitle a user to them, and building your own screen over them does not change what the licence covers. The two honest answers are to buy the licence, or to redesign so those people work with your own tables and a licensed user is the one who touches the Dynamics 365 record. |
| Replacing a standard module because the team says it does not fit | Extend, after checking the module was ever actually configured | A meaningful share of "it does not fit" turns out to be a module nobody switched on or nobody configured past the demo. Rebuilding queues, entitlements, or forecasting as a canvas app is a great deal of work to arrive somewhere behind where you started. |
The general rule underneath the table: extend when you are enhancing a record that already exists in Dynamics 365, and build separately when the process has its own records and its own audience. Everything else is a licensing question or a coexistence question, and both are below.
What each route costs to licence
This is where the decision is usually made, and it is made on the wrong number about half the time we are asked to review it. Read the third column before the second one.
| Licence | Order of size at list | What it actually reaches |
|---|---|---|
| Power Apps per app | Around USD 5 per user, per app, per month at list | One application for one user, over standard Dataverse tables and the tables you create yourself. It does not reach the restricted tables that belong to a Dynamics 365 application. |
| Power Apps Premium, the plan previously sold as per user | Around USD 20 per user per month at list | Unlimited applications and portals for that user, still over standard and custom tables only. Break even against per app arrives at roughly four applications per person, which most organizations never reach for the same user. |
| A Dynamics 365 Customer Engagement base application: Sales Enterprise, Customer Service Enterprise, Field Service | Roughly USD 65 to 105 per user per month at list, depending on application and tier | The restricted tables for that application, plus Power Apps and Power Automate rights within the context of it. This is the licence a separate app cannot substitute for, and the reason most build to avoid licensing plans do not survive contact with a licensing specialist. |
| An attach licence for a second application | Around USD 20 per user per month at list | A qualifying second application for a user who already holds a base licence. It is routinely missed, and it is usually the cheapest answer when a second team needs the same records. |
| Team Members | Around USD 8 per user per month at list | Read mostly, with a narrow set of write scenarios and its own designated apps. It is not a route to giving a wide audience a bespoke screen over case or opportunity records, and using it that way is a licensing finding rather than an architecture. |
Those figures are orders of size, not a budget input. Microsoft revises list pricing, and volume, term, and regional agreements move it further, so check the current price list and your own agreement before anybody multiplies by a headcount. The durable part of the table is the third column, because entitlement changes far more slowly than price. If the licence question is the reason you are reading this at all, our guide to Dynamics 365 licensing costs and renewal negotiation covers rightsizing seats and preparing for the conversation with Microsoft.
What each route costs to keep, over years rather than months
Both routes work on the day they ship. They diverge at the second release wave and at the first change of owner, which is the timescale the decision should actually be made on.
Layering, and what a release wave can move underneath you
When you customize a component that ships in a Microsoft managed solution, your change becomes a layer above theirs rather than an edit to it. The base layer keeps moving with two release waves a year and your layer keeps winning, which is fine until the day a change beneath you was the fix you needed. The solution layers view on a component is where you find out what is actually stacked on a form, and on an inherited environment it is usually the first honest picture anybody has had. Tables you create yourself in a solution of your own have nothing underneath them, and that is the single largest structural argument for building separately.
Regression testing is the standing cost of extending
Extending means your work shares a surface with a product that updates on a schedule you do not set. The manageable version is a test environment with a realistic copy, the early release channel enabled there, and a written list of what gets retested each wave: the pricing logic, the embedded app, the code components, the flows on the case, and the integrations. That list is short and it is worth writing once. The unmanageable version is finding out from a user. Budget this deliberately, in the same place you budget the twenty hours a month for support in year two.
A separate app is not maintenance free, it is differently maintained
Building outside Dynamics 365 moves the work rather than removing it. You now own the data model, the security model, the reporting, the connector versions, and the answer to who changes it when the process changes. What ages worst is a copy of data whose real owner is somewhere else, because a copy is a synchronisation job with an error path, a reconciliation, and an owner, and it is almost never scoped as one at the start.
The question that settles it in year two
Where does the truth about a customer live. If the honest answer after your build is two places, you have bought an integration you did not put in the budget, and you have bought it permanently. If the answer is one place, both approaches are defensible and the decision comes back to licensing and to release cadence, which are the two things you can actually calculate.
Coexistence, which is what most real answers look like
The framing of one against the other is useful for deciding where a requirement lives, and misleading as a description of a finished system. Almost every environment we work in runs both. These are the patterns that let it do so without an integration in the middle.
One environment, one Dataverse, is the default answer
A Power App and a Dynamics 365 application in the same environment share the same tables, the same security roles, the same auditing, and the same reporting. That means there is no integration to build, no synchronisation to monitor, and no second copy of anything. Separate environments are justified by a real constraint, such as a different data loss prevention boundary, a data residency requirement, or a genuinely different owner and release cadence. Anything short of that is an integration you have chosen to build for yourself.
A canvas app embedded on a model driven form
A canvas app can be hosted directly on a form with the current record passed into it, which suits a guided task or a screen shaped for a phone sitting inside a record people already open. The trade is honest: it is a second artefact with its own connections, its own solution, and its own testing. Connections owned by a named person rather than a service account are the failure we meet most often here, and it is always found the week after that person changes role.
A custom page inside the model driven app
The more current pattern is a low code page that belongs to the model driven app itself, reachable from the site map or from a command, opening full page or as a side dialog. It stays inside the app navigation and the app security rather than sitting as a guest on a form, and for most of the cases people used to embed a canvas app for, this is now the cleaner choice.
A code component where the need is a control rather than an app
If the requirement is one interaction that the form designer does not have, a PCF code component keeps it inside the record, inside the solution, and inside the security model, with no second application to license or maintain. It is the smallest possible version of extending, and the one most often skipped in favour of something much larger.
Power Pages when the audience is outside the organization
External users read and write the same Dataverse tables through a portal, governed by table permissions and web roles rather than by security roles on internal licences. It coexists with both approaches, and it is the correct answer to a surprising share of requests that arrive described as a new Power App.
The honest trade, from projects rather than from feature lists
Each side has a real advantage and a real cost, and each example below is a project shape we meet regularly rather than a named client. Read the costs column of the option you have already decided on.
Extending Dynamics 365
What it gives you
- One data model, one security model, one set of reports, and no integration to build, monitor, or explain to an auditor.
- Queues, routing, entitlements, service level agreements, forecasting, and the rest of the standard machinery keep working on the records your extension touches.
- The users already hold the licence and the app is already in their navigation, so adoption is a change to something familiar rather than a launch.
What it costs you
- Your work sits above Microsoft components that move twice a year, so regression testing becomes a permanent line rather than a project task.
- Each extension raises the price of the next one on the same form. A form carrying a decade of additions is the single most common thing we are asked to untangle.
- The licence is a floor you cannot design your way under. Anyone who touches the record needs a Dynamics 365 licence whatever you build over it.
A project this describes. A distributor whose quoting rules could not be expressed in a price list. The tempting answer was a separate quoting app for the sales team. It would have needed its own product list, its own customer list, a synchronisation job in both directions, and a Dynamics 365 licence for the same people anyway, because quote and order are restricted tables. Extending was cheaper on every axis that mattered: pricing logic as a plug-in, a handful of fields, and the standard quote to order to invoice path left alone.
Building a separate Power App
What it gives you
- Your own tables in a solution with your own publisher, and nothing underneath them that a release wave can move.
- Per app licensing for people who need one screen a fortnight, which is exactly the population a full application licence prices out of existence.
- A smaller blast radius. The app can be rebuilt or retired on its own without a negotiation with everyone who depends on the CRM.
What it costs you
- You own the data model, the security model, the reporting, and the answer to who maintains it when the person who built it moves on.
- If it needs customer data you either share the environment or you build a copy, and a copy is a synchronisation job with an owner, an error path, and a reconciliation that nobody scoped.
- It is invisible to the standard machinery. Nothing about queues, entitlements, or forecasting applies to your tables unless you build the equivalent yourself.
A project this describes. A services business that wanted engineers to log site visits from a phone. Only a few of them opened the CRM at all, the visit related to a site rather than to a case, and no restricted table was involved anywhere in the process. A canvas app on its own Dataverse tables, in the same environment, licensed per app, was the right answer and cost a fraction of licensing the whole field team. The one design decision that mattered was that the app looked up the real account record rather than holding its own copy of the customer list.
If the answer lands on extending, the work is Dataverse modelling, server side logic, and code components, which is what our Dynamics 365 and CRM development service covers. If it lands on building separately, it is canvas and model driven app work, Power Automate, and the Dataverse model underneath them, which sits under Power Platform and Power Apps development. The same engineers do both, which is the reason we can afford to give you this answer straight rather than route it towards whichever practice needs the work.
If your organization is making this call repeatedly rather than once, the answer is not a better decision each time. It is a standard: an environment strategy, a data loss prevention policy, naming and solution conventions, a component library, and a written rule for which requirements go where. That is what a Center of Excellence is, and our guide to building a Power Apps Center of Excellence with a nearshore team sets out what it contains, how it is stood up, and how the knowledge is transferred back to your own makers.
What are the signs the build has already gone past the line?
These are the patterns we meet when we are asked to take over an environment somebody else built. None of them mean the work is worthless, and most of what we inherit is worth keeping. They do mean the next change will cost more than the last one.
Changes are made directly in production because there is nowhere else to make them, and everything lives in the default solution.
Production flows and connections are owned by one person's account, and that person has changed role, changed team, or left.
There is JavaScript on forms or a plug-in in the environment, and nobody currently employed can say what it does or where the source is.
Users have quietly gone back to a spreadsheet for the part of the process the system was bought to fix, and are re-entering the result afterwards.
Every new requirement now starts with a workaround for a previous workaround, and estimates keep growing for changes that sound small.
Reports disagree with each other, and the conversation has moved from what the numbers mean to which report to trust.
The go live date has moved more than once and nobody can state, in one sentence, what is left to do.
If several of those are true, the useful next step is an assessment rather than another sprint. Our rescue and takeover guide sets out what a proper assessment covers, and the health check is the smaller version for a build that is running but unproven.
What is the middle path most teams should take?
The choice is rarely do everything yourself or hand everything over. Four shapes of engagement sit between those two, and for most in house teams one of them is the right answer.
A design review before you build
The cheapest expert hours in a Power Platform project are the ones spent before anything exists. Someone reads your process, your intended data model, your environment plan, and your security requirements, and tells you which parts are standard configuration and which parts are the walls above. Buyers who do this arrive at the same destination having built less.
A specialist for the part that is genuinely code
Your makers keep the apps, the flows, and the model, and a developer builds the piece that has to be built: the pricing plug-in, the integration, the code component, the migration. This is the most common shape of our work with in house teams, and it keeps ownership where it belongs rather than making a consultancy the permanent gatekeeper of your own system.
A health check on what already exists
If a build is running but you cannot tell whether it is sound, an assessment of the environment, the solutions, the customizations, the security model, and the integrations tells you what is fine, what needs work, and what has to be rebuilt. It is a much smaller purchase than a rescue and it is the one that prevents needing a rescue.
A takeover when the project has stopped
Where an implementation has stalled or a supplier relationship has ended, the work is to assess honestly, stabilise what users depend on, and finish. We do this as a named service, including on environments built by somebody else, and the first deliverable is always an assessment rather than a promise.
Whichever of those four you buy, the work that comes next is the same, and it is work you can start before a supplier is chosen. The pre-implementation checklist further down this page is the nine phases and 66 checkpoints we work through at the start of a Customer Engagement or Project Operations project, and it is downloadable.
What does this actually cost, honestly?
First, where the money actually goes, which is the part most comparisons leave out. The section straight after this one turns it into a budget you can defend, with relative cost by supplier origin and effort ranges for the Caucasus region.
Do it yourself is not free, it is differently paid for
The licences are the same either way. What changes is whose time is spent, and it is usually the time of the person who understands the business best, taken from the job they were hired to do. That cost is real and it never appears on an invoice, which is why it is systematically left out of the comparison.
The expensive line item is rework, not build
Almost nothing we are called in to fix was expensive to build. It was expensive to unwind: a data model that has to change after a year of records, a security model that has to be redesigned once a second business unit exists, a single environment that has to be split, an integration that has been silently dropping records. The cost of getting these wrong is not proportional to the cost of getting them right.
Ask what the second year costs, not the first
Any route can deliver something that works in month one. The question that separates them is what happens at the next release wave, at the next change request, and on the day the person who built it is unavailable. Decide who owns the system, where its source lives, and how a change reaches production, and the first year price is much easier to compare honestly.
What actually drives a quote
We do not publish fixed prices, because scope drives everything: how many users and apps, how much of the process is standard configuration against custom development, how much data has to be migrated, and how many systems have to talk to each other. We quote on time and materials or fixed price per milestone after a scoping conversation, so you see the basis before you commit. Delivering from Yerevan puts our rates well below Western European and US consultancies for the same seniority of engineer.
How do you budget a realistic project for the Caucasus region?
Everything above tells you which parts of your project need expert help. This section tells you what those parts cost when you are buying in Armenia, Georgia, or Azerbaijan, or buying from the region while sitting in Europe. It is built so you can produce the number yourself rather than wait for a proposal to find out.
How to read the figures. The ranges below are planning figures taken from what we scope in this market. We do not publish hourly rates, so supplier origins are compared by relative cost and the effort table is stated in engineer days. They are not a Solzet price list and they are not a quote for your project. They are wide on purpose, because a narrow number stated without seeing an environment is decoration. Use them to build a budget you can defend internally, then hold that budget against two or three real proposals.
Relative partner cost by where the team sits
The same engineer, with the same certifications, doing the same work, costs a different amount depending on which country pays their salary. On a project that is mostly configuration this is the single largest lever on the total, which is why it is the first table rather than the last.
| Where the team sits | Relative cost | What the rate actually buys |
|---|---|---|
| Independent freelancer in the Caucasus | Lowest hourly cost | One skill set and no cover for holiday, illness, or a better offer. Fine for a bounded task, and the cheapest way to end up owning code nobody can maintain if it is used for a whole build. |
| Armenian consultancy (Yerevan), certified senior engineer | Competitive rates, quoted after scoping | A senior, certified engineer on the build rather than on the pitch, GMT+4, and a company that can be held to a contract. Solzet delivers from here, and we quote per project after a scoping conversation rather than from a published rate. |
| Georgian or wider Caucasus consultancy | Similar to Yerevan | Broadly the same economics as Yerevan. Differences that matter are depth of Dynamics 365 Customer Engagement experience and continuity of staff, not the headline rate. |
| Central and Eastern European nearshore (Poland, Romania, Baltics) | Higher | A deeper local market and an EU entity on the contract. For an EU buyer that removes a procurement conversation. For a buyer already in the Caucasus it is mostly a higher price for the same seniority. |
| Western European consultancy (Germany, Netherlands, Nordics, UK) | Substantially higher | Same time zone as a Western European buyer, a local legal entity, and local employment costs inside the rate. On a project that is mostly configuration, this is the single largest lever on the total. |
| US consultancy | Among the highest | US hours and US contracting. Rarely the right answer for a Caucasus buyer unless the parent company mandates it. |
| Global systems integrator | Highest | Programme governance, multi-country rollout, and contractual weight. Ask specifically who builds, because the architect who presents is often not the engineer who delivers. |
A rate is only half of a budget and the less important half. A cheap rate spent on the wrong design costs more than an expensive rate spent on the right one, which is why the effort table comes next rather than a discount argument.
What actually drives the effort, line by line
Multiply these day ranges by the rates in a real proposal and you have a budget. The ranges assume a first rollout of one Dynamics 365 Customer Engagement app, which is the shape of most regional projects, and they are engineer days rather than elapsed days.
| Line item | Indicative effort | What pushes it to the top of the range |
|---|---|---|
| Discovery, process mapping, and a solution design worth building against | 5 to 12 engineer days | More stakeholders than one workshop can hold, a process that differs by country or branch, or a business that has never written its process down. |
| Core configuration of one standard app (Sales or Customer Service) | 15 to 35 engineer days | Distance from how the standard app already works. Every requirement that says "but we do it differently" moves this up, and most of them are worth challenging first. |
| Data migration from one legacy system | 10 to 30 engineer days | History, attachments, ownership and original dates to preserve, duplicates to match rather than reload, more than one source system, or a row count high enough that throttling decides the schedule. This is the line item most often underestimated by an order of size. |
| Each integration with a system that has no maintained connector | 8 to 25 engineer days each | Its own authentication, pagination or batching, webhooks to receive, ordering guarantees, idempotency so a retry does not duplicate a record, and an alerting path when it fails at three in the morning. Count your endpoints before you accept any fixed price. |
| Custom pricing or discount logic as a plug-in | 5 to 15 engineer days | Compounding tiers, per customer agreements with validity dates, bundle logic, or a margin floor that has to block a save. This is wall one above, and it is the most common single reason a regional DIY build ends up hiring. |
| Each PCF code component | 5 to 20 engineer days each | Interaction complexity, offline and mobile behaviour, accessibility, and how much data the component has to hold on screen at once. |
| Environments, solutions, and a deployment pipeline | 3 to 8 engineer days | Almost nothing, which is why skipping it is such a poor trade. Doing it after a year of building in production is a multiple of this number. |
| Security model design | 2 to 6 engineer days | A second business unit, hierarchy security for managers, field level security, or a partner network that has to see some records and not others. |
| Training, adoption support, and hypercare after go live | 5 to 15 engineer days | Number of user groups, number of languages, and whether the people affected were involved before the demo. The cheapest adoption budget is spent during design, not after launch. |
| Ongoing support in year two | From around 20 hours a month | Release wave updates, new flows as processes change, reporting requests, and PCF upgrades. Budget it deliberately rather than discovering it, whichever route you take. |
Licences are not in that table and should be budgeted separately, because they are the one line that does not change with who builds the system. If your renewal is the reason you are reading a cost page at all, the guide to Dynamics 365 licensing costs and renewal negotiation covers Per App against Per User, rightsizing seats, and how to prepare for the conversation with Microsoft.
Do it yourself against partner-led, line by line
The comparison people usually run is an invoice against zero. This one counts your own team as well, because their time is the cost that never appears on an invoice and is systematically left out.
| Cost line | Do it yourself, in-house makers | Caucasus partner-led | Western European partner-led |
|---|---|---|---|
| Hourly cost of the person doing the work | The fully loaded cost of an in-house maker, salary plus employment costs, and it is real money even though it never reaches an invoice | Competitive rates, quoted after scoping and billed only for days worked | Several times the regional rate for the same seniority, billed only for days worked |
| Licences | Identical. Dynamics 365 and Power Platform licensing does not change with who builds the system | Identical, though a partner should be reducing the seat count rather than growing it | Identical |
| Elapsed time to a working first app | Longer, because the work competes with the day job of the person who understands the business best | Shorter, and the same time zone means a decision does not cost a day | Shorter, but a Caucasus buyer loses hours to the time difference and to procurement |
| The eight walls above | Each one is a stop. Either the requirement is dropped, or it becomes a workaround, or you hire anyway and pay for the workaround to be removed first | Priced as line items you can accept or defer, using the effort ranges above | The same line items at two to four times the rate |
| Rework risk | Highest, and it is the real cost. A data model changed after a year of records, a security model redesigned for a second business unit, or one production environment split into three | Lower, provided the environment and solution strategy is in the scope you signed. Check that it is | Lower, at a higher price for the same protection |
| Year two ownership | Your team, which is the best outcome available if the foundations were laid properly | Your team, with a named partner for the parts that are genuinely engineering | Often the partner, at a rate that makes every small change a decision |
| Where this is the right answer | Standard process, ordinary volumes, small and clean data, nothing bespoke to integrate, and being wrong is cheap to redo | Anything that hits two or more of the eight walls, and any build that has become business critical | A multi-country programme, a mandated local entity, or governance requirements that outweigh the rate |
The same arithmetic decides platform choices as well as supplier choices. Our cost comparison of Power Apps against standalone field inspection platforms works a single app through it, and is the clearest worked example on this site of a build cost weighed against a per user subscription.
Fixed price or time and materials
This choice moves the total more than the rate does, because it decides who carries the risk on the line items nobody can size yet.
Fixed price per milestone
Correct when the scope is genuinely knowable in advance: a defined app, a named list of integration endpoints, a counted set of records, a fixed number of custom components. It transfers risk to the supplier, and a supplier who accepts it without those numbers in writing has either priced the worst case into your quote or intends to charge for change requests. Ask for the assumptions behind the price as a numbered list, and treat anything the list does not name as a change.
Time and materials against a backlog
Correct when the scope will be discovered as you go, which describes most first Power Platform builds honestly assessed. It is cheaper than fixed price for the same work because you are not paying the risk premium, and it demands something from you in return: a product owner who can prioritise, and a look at the burn every sprint. Ask for a not to exceed ceiling per phase if your finance team needs a number to approve.
A dedicated resource on a monthly contract
Correct when you need capacity rather than a project, typically three to twelve months. The rate per hour is usually the lowest of the three because the commitment is longer, and the buyer risk is different: you are responsible for keeping that person usefully busy. This is the model most often used by Microsoft partners buying our capacity rather than by end clients.
The hybrid most regional projects should use
Fixed price the parts that are knowable, such as discovery, environment and solution setup, and core configuration of a standard app. Run migration, integrations, and anything custom on time and materials with a ceiling, because those are the three where a fixed price is a guess with a margin attached. Any supplier who will not split a quote this way is telling you something about how well they understand your scope.
Nine questions for any partner in the region, including us
Buying Dynamics 365 delivery in the Caucasus has its own procurement questions, and the ones that bite are rarely technical. Ask all nine, write the answers down, and compare proposals on those rather than on the headline total.
Give me a rate card by role, not one blended number, and tell me which roles are on my project for how many days.
A blended rate hides the mix. The same total buys very different outcomes depending on whether it is senior engineer days or junior days with an architect who signs off at the end. Ask for the day counts against the line items in the table above and you can check the arithmetic yourself.
Is project management, QA, and account management billed, and at what proportion of build time?
It is legitimate to bill it and it is legitimate to include it. What is not legitimate is discovering it after signature. Ask for the number and compare like with like across proposals, because one supplier folding it into the rate and another adding it on top makes a cheap quote look expensive and the reverse.
Which legal entity contracts with me, in what currency am I invoiced, and how is VAT handled?
Armenian and Georgian consultancies commonly contract B2B and invoice in USD or EUR. An EU or UK buyer should confirm reverse charge treatment before the first invoice, and a local buyer should confirm the entity is the one that will actually carry the warranty. This is a five minute question that prevents a finance problem in month three.
Will the engineer I interview be the engineer who builds, and what happens if they leave?
The regional market is small and good Dynamics 365 engineers are portable. Ask how many people will have working knowledge of your environment, and whether there is cover for holiday and illness. A one person supplier at a good rate is a single point of failure whatever the contract says.
What Microsoft certifications do the delivery engineers hold, and can I verify them?
For Customer Engagement and the Power Platform the relevant ones are PL-200, PL-400, and PL-600, and MB-210, MB-230, and MB-240. Certifications are not proof of judgement, but an unwillingness to name them is informative.
Who owns the source code, the solutions, and the documentation, and where do they live?
The answer should be that source sits in a repository you own, that solutions are exported and importable by your own admin, and that documentation is good enough for another developer to continue. Everything else is a supplier making itself difficult to replace, and the price of that shows up in year two rather than in the quote.
How many hours of daily overlap will I actually get, and how do I reach you when something breaks?
A Yerevan or Tbilisi team at GMT+4 shares working hours with the rest of the Caucasus, gives roughly four to six hours of daily overlap with Western Europe, and reaches into the US morning. Ask for the escalation path and the response commitment in writing rather than the promise of availability.
Show me the migration plan and the rehearsal before you quote the migration.
A supplier who quotes a migration without asking about record counts, attachments, duplicates, and whether history is required has not scoped it. That is the line item that overruns, and it is the one worth being difficult about at proposal stage.
What does the first month look like if this goes wrong, and have you taken over another supplier work before?
Ask for the shape of an assessment rather than a reassurance. A partner who does takeover work will describe a process. A partner who does not will describe a feeling.
The delivery models behind those questions, meaning what a local Yerevan consultancy, a freelancer, a global integrator, and a distant offshore agency each realistically give you, are compared side by side in our Yerevan and Armenia local delivery guide, together with a due diligence checklist you can apply to any of them.
Which eight questions settle it?
Answer these about your own project. Each one points at a specific wall above, so the output is a list of the parts you need help with rather than a verdict on the whole thing.
Does anything in your pricing depend on more than a price list and a quantity band?
If yes, you are at wall one. Confirm it early, because the workaround people reach for first is a flow that overwrites the line total, and that is the version that breaks quietly.
Do your service commitments vary by customer, contract, or region?
If yes, map them against applicable when, pause, and success conditions before you promise them to anyone. If they do not map, the requirement needs design work rather than more configuration.
Are you bringing in history, or just today?
History means relationships, ownership, original dates, and attachments, and it means reconciliation. Starting clean is a legitimate and much cheaper decision, and it should be a decision rather than a discovery.
How many rows will the biggest table hold in three years?
If the honest answer is hundreds of thousands or more, canvas app delegation and query design stop being theory. Test against realistic volume before anybody depends on a screen.
Does anything outside Microsoft 365 have to read or write records?
If yes, the questions are authentication, retry, duplicate prevention, and who gets told when it fails. A connector answers the first part of that and none of the rest.
Where do you make changes today?
If the answer is production, that is the wall that costs the most later. Splitting environments and moving to managed solutions is easier now than at any point in the future.
If the person who built this were unavailable for a month, what would happen?
If the answer is that changes stop, you have a single point of failure regardless of how good the build is, and that is an ownership problem rather than a technical one.
Is anyone still doing the old process in parallel?
A spreadsheet running alongside the system is the clearest signal that a requirement was never actually met. Find out which one before adding anything new.
What belongs on the Dynamics 365 pre-implementation checklist?
You have worked out which parts of the project are configuration and which parts are engineering, and you have decided to buy the second list. This is what to do next, in the weeks before anybody opens a maker portal. Nine phases, and every item is a decision with a named owner and a written answer rather than a theme to keep in mind. Most of them cost nothing now and are expensive to reverse later, which is the only real test of whether something belongs on a pre-implementation checklist at all. Work through it yourself, or hand it to the two or three partners you are shortlisting and watch which of them has answers ready.
Pre-Implementation Checklist for Dynamics 365 Customer Engagement and Project Operations
The same nine phases and 66 checkpoints set out below, as a print ready page with a tick box against every line. Take it into a scoping call, or send it to the partners you are shortlisting and see which of them already has the answers.
Opens as a print ready page. Use Ctrl+P or Cmd+P and choose "Save as PDF", with background graphics enabled, to keep a copy.
Scope and ownership, before anything technical
Week zero
Every item here is a sentence somebody has to write down. None of them require the platform, and all of them are quoted against.
State the outcome in one sentence, and the measure that proves it
Not "implement Dynamics 365". Something closer to "every quote is approved and out within one working day, and we can say what the pipeline is without exporting anything". If nobody can write that sentence, the requirements list will grow until the budget runs out.
Name one executive sponsor and one decision maker per process
A name each, not a department. The single most reliable predictor of a project sliding is a design question that sits unanswered because it belongs to a committee.
Split requirements into must have and nice to have, with a date against each
A nice to have with no date is a must have in disguise. This list is also what protects a fixed price milestone from becoming an argument.
Decide who owns the system in year two, and budget for it now
A named person or team, a support allowance, and a route for a change request. Plan from around twenty hours a month in the second year for a single Customer Engagement app. Unowned systems are the ones we get called about.
Split the scope into configuration and engineering, using the eight walls above
This list is the thing you actually hand a consultant. It turns "we need a Dynamics 365 partner" into a scope with line items, and it is what lets you buy help for one wall rather than for the whole project.
Fix the licence count and the licence mix before you scope the build
Base application licences, attach licences for a second application, Team Members, Power Apps per app, and Power Pages for anyone outside the organization. Design decisions that assume the wrong licence are found at renewal, which is the most expensive moment to find them.
Write down what phase one delivers and what is explicitly deferred
The deferred list matters more than the delivered one. It is the document you point at when somebody asks in week six why the thing they never mentioned is not being built.
Environments, solutions, and the route to production
Before the first configuration change
Wall six on this page is the most expensive one to unwind and the cheapest one to avoid. These seven items are how you avoid it.
Stand up development, test, and production as separate environments
Three environments from day one. Building in production because it is quicker is the decision that costs a year later, and it never feels like a decision at the time.
Create your own publisher and prefix, and never build in the default solution
A named unmanaged solution in development, with your publisher on it. Components created in the default solution are the ones nobody can move, package, or cleanly remove afterwards.
Agree that production and test only ever receive managed solutions
Managed into test and production, unmanaged only in development. This is what makes a component removable and a layer predictable, and it is a policy rather than a tool.
Pick where the source lives and export into it from the first week
Azure DevOps, GitHub, or whatever your organization already uses. Unpacked solutions in a repository you own, not a zip file on a consultant laptop. Confirm in writing that this is yours at the end of the engagement.
Set the data loss prevention policy before the makers arrive
Which connectors are business, which are not, and which are blocked. Retrofitting a policy onto flows people already depend on is a negotiation. Setting it first is an afternoon.
Decide the Dataverse region at creation, against your data residency obligation
Check what the customer contract, the personal data law you are subject to, and any EU client of yours require before the database exists. Moving an environment between regions later is a support request and a plan, not a setting.
Set the base currency and the base language at creation, and check them twice
Both are fixed when the Dataverse database is created and cannot be changed afterwards. Phase six covers what the currency choice actually commits you to, and it is the single most common irreversible mistake we find on regional environments.
Map security roles to process owners
During design, before the first record exists
Security is the wall that needs no code, which is exactly why it gets left. Ownership and business unit changes move records later, not just permissions.
List every process and put one owner name against it
Quote approval, case escalation, discount authorisation, project contract sign off, credit hold. A person, not a role title and not a department. This list is the input to every item below it.
Design business units around how records must be separated, not around the org chart
The org chart changes every year and the separation requirement rarely does. Business units built to mirror reporting lines are the ones that have to be rebuilt after the first reorganisation.
Decide user ownership or team ownership per table, before there are records
Records owned by a person disappear from view when that person leaves. Records owned by a team survive it. Changing your mind later means moving every row.
Turn each named owner into a security role, privilege by privilege
Write out create, read, write, delete, append, append to, assign, and share for each table, at the depth you actually mean. If the answer to any of them is "everyone, organization wide", say why in the same document.
Identify the columns that need field level security
Cost, margin, discount ceiling, salary or day rate on a resource, and anything personal. It is a short list on most projects, and it is far cheaper to secure a column before people have grown used to seeing it.
Decide how managers see their team, deliberately
Hierarchy security, a wider business unit, or a team. Three different answers with three different maintenance costs. Picking one by accident is how a sales manager ends up with organization wide read on everything.
Agree who can export to Excel and who can run a bulk delete
The two privileges most often left on by default and the two with the largest consequences. Export is your data leaving. Bulk delete is your data leaving permanently.
Write down what happens when somebody leaves
Records reassigned, flows reassigned, and connections reassigned. Flows and connections owned by an individual account are the failure we meet most often, and it is always discovered the week after that person changes role.
Clean the legacy data before it becomes your problem
Start in parallel with design, not before go live
Migration is the line item most often underestimated by an order of size. Almost all of that underestimate is cleaning, not loading.
Count the rows per source table today, and write the numbers down
Accounts, contacts, open and closed transactions, notes, and attachments. The counts decide the approach, the tooling, and the price. A partner who quotes a migration without asking for them has not scoped it.
Decide the history cut off explicitly
Two years, five years, open records only, or everything. Starting clean is a legitimate and much cheaper decision, and it should be a decision made in a meeting rather than a discovery made in the final week.
Pick the one canonical customer list, and retire the others
Only one system can win. Where the accounting system, the sales spreadsheet, and the old database disagree, name in advance which one is right and who arbitrates the exceptions.
Choose a matching key you can defend, then deduplicate at source
A tax identification or state registration number beats a company name every time. This matters more in the Caucasus than in most markets, because the same organization commonly exists once in Armenian or Georgian script and again in Latin transliteration, and name based matching silently treats them as two customers.
Normalise phone numbers and addresses before the load, not after
International format for every number, including the country code, so that +374, +995, and +994 records behave the same as European ones in search, duplicate detection, and any telephony you add later.
Decide what ownership and created on mean for migrated rows
If history has to mean anything, original dates and original owners have to survive the move, and that is a different and larger piece of work from loading current data. Say which one you are buying.
Create alternate keys on the source system identifier
With a key on the legacy identifier, a reload updates the row it already created instead of making a second one. Without it, the second attempt at a migration doubles your data, and there is always a second attempt.
Rehearse into test at full volume, then reconcile and get a business sign off
Row counts, financial totals, and a spot check by the people who know what the records should say. Migration rehearsal is the step that gets cut when a date slips, and it is the one that decides whether users trust the system in week one.
Define every integration endpoint on one page
During design, before anyone builds a flow
An integration that has never been given a retry policy looks fine for months and then quietly drops the record that mattered. This page is what prevents that.
List each endpoint with system, direction, trigger, and volume
One row per endpoint: what it talks to, which way data moves, what starts it, records per day, and records at peak. Count the rows before you accept any fixed price, because each one is an eight to twenty five engineer day line item when no maintained connector exists.
Write the field level mapping for each direction
Including what happens to a field the other side does not have, and which system wins when both have changed the same record. Undecided conflict resolution is decided by whichever job runs last, which is not a design.
Name the authentication method and the account that owns it
A service principal or an application user, never a named employee. Every integration authenticated as a person is a resignation away from an outage.
Decide the idempotency key so a retry cannot duplicate a record
The alternate key on the external identifier does most of this work. Without one, the first network timeout becomes two invoices for the same order, and it will be found by a customer rather than by you.
Set a retry policy and configure run after behaviour on every flow
Both are defaults nobody changes and both decide what happens on the second attempt and on a partial failure. This is the difference between an integration that recovers and one that stops without telling anybody.
Name the human who gets alerted on failure, and the channel that reaches them
A failure notice in a mailbox nobody reads is not monitoring. Decide who is woken up, how, and what they are expected to do, and test it once before go live.
Confirm channel and number availability for your countries before promising them
Email, telephony, and messaging channels are not uniformly available or uniformly provisioned across every country, and lead times on numbers are real. Verify for Armenia, Georgia, or wherever your users sit before a channel appears on a project plan.
Multi-currency and money, the way it works in the Caucasus
Before the environment is created, and again during design
This is the phase a generic checklist does not have. Regional projects almost always quote in one currency, report in another, and invoice in a third.
Choose the base currency against your statutory reporting, and understand it is permanent
The base currency is set when the Dataverse database is created and cannot be changed afterwards. If contracts are written in US dollars or euros while statutory reporting is in Armenian dram or Georgian lari, decide which of those the system reports in before the database exists. Getting this wrong means a new environment and a full migration.
Add every transaction currency you will ever quote in, at the start
Each with its symbol and its precision. Adding one later is easy, but records already saved in the wrong currency are not, and a quote raised in the wrong currency is a commercial conversation rather than a data fix.
Decide who maintains the exchange rate, and how often
The exchange rate on a currency record is a static number that somebody has to update. There is no automatic feed built in. Name the person or the flow, name the source rate you use, and write down the frequency, because an untouched rate is the default state of most environments we audit.
Agree with finance what a base currency report actually means
Base amounts are calculated using the rate in effect when the record is written, and changing the rate later does not restate rows that already exist. A base currency total is therefore a mixture of historical rates, which is usually correct and almost never what somebody assumed. Settle it before the first board pack.
Set currency and pricing decimal precision before any price data exists
Two decimals is fine for dram against dollar totals and is not always fine for a unit price on a low value item sold in thousands. Test the rounding against how your sales team actually quotes, at the point where it is still a setting.
Build one price list per currency, and check the rounding rules on each
Pricing method, rounding policy, and rounding option per price list item. This is standard configuration and it covers more commercial models than most teams expect, which is worth confirming before anybody scopes a pricing plug-in.
Decide which system issues the legally valid invoice
In Armenia and Georgia the tax invoice is issued through the state electronic invoicing system, so Dynamics 365 is the commercial record rather than the fiscal one on almost every regional project. Decide that explicitly, and decide which field carries the reference between the two, because reconciling them by hand is the workaround that never goes away.
Model VAT treatment as data on the customer, not as knowledge in the sales team
Domestic supply, export of services, reverse charge for an EU business customer, and whether the customer is registered. A field on the account and a rule that reads it. Left as tribal knowledge, it becomes a correction after an audit.
Local compliance, calendars, and language
During design, before any service commitment is signed
The regional items that are invisible from a headquarters implementation guide and obvious to anyone who has run a rollout at GMT+4.
Load the right public holidays into the business closure calendar
Armenian, Georgian, and Azerbaijani public holidays are not the same list, and none of them match a default calendar. An SLA clock runs straight through a holiday nobody entered, and the first anybody hears of it is a breach report in January.
Account for the daylight saving gap in service hours and in shared support windows
Armenia does not change its clocks. European customers do, so the overlap with a team in Yerevan moves by an hour twice a year. Write the support window in a way that survives that, and set the customer service schedule so the SLA does too.
Set the personal data rules before there is personal data
Armenian and Georgian personal data law, plus GDPR if you sell into the EU. Decide retention, decide who may export, and decide what a deletion request actually does to a record and to its audit history. This is a design decision, not a policy document.
Confirm the interface languages you need exist as language packs
Check the current supported language list against what you are about to promise, and decide the fallback where a pack does not exist. English and Russian cover most regional teams in practice, and it is better to say so at the start than after a demo.
Set date, number, and currency formats per user, then test them
A comma decimal separator meeting a period one is a data quality incident rather than a display preference, and it shows up in imports, exports, and anything anyone builds in Excel.
Decide which documents must exist in which language
Quotes, invoices, and customer facing correspondence. Interface language and document language are separate decisions with separate work behind them, and only one of them is a setting.
Project Operations, if projects are in scope
Before scoping, because the deployment choice changes the size of the programme
Project Operations sits on the same Dataverse as the rest of Customer Engagement, which makes it look like one more module. The decisions below are what actually determine its cost.
Choose the deployment type before anybody scopes the work
The lite deployment keeps the path from deal through to invoicing inside Dataverse, which suits most regional professional services firms. Deployments that connect through to a separate finance back end are a materially larger programme with a different integration, a different licence, and a different team. Choosing this in week six rather than week zero is an expensive way to find out.
Decide the work breakdown granularity, and who maintains it
Actuals are only ever as good as the plan they are booked against. A hundred line schedule that nobody updates produces margin reporting that is worse than no reporting, because people believe it.
Set up resource roles and a role price per currency
Roles, skills, and a price per role in every currency you contract in. This is where the multi-currency decisions in phase six become real, because a role price list in the wrong currency quietly misprices every estimate built on it.
Decide chargeability by transaction class, and which expenses are never billed
Time, expense, and material each need a default and a set of exceptions. The exceptions are what people argue about at invoicing, so they belong in configuration rather than in an email thread.
Choose the billing method per contract line, not per contract
Fixed price with milestones for the knowable parts, time and material with a not to exceed for the rest. Exactly the split described in the fixed price against time and materials section above, applied to your own clients this time.
Configure the time and expense approval chain, and name who chases the missing entries
The approval chain is configuration and it takes an afternoon. The discipline is a person, and without one the whole module produces confident numbers built on half the timesheets.
Decide how a won quote becomes a project contract, and who is allowed to do it
This is the handover point between the sales side and the delivery side, and it is where regional implementations most often end up with two versions of the same commercial agreement.
Confirm which currency the margin report actually uses
The contract currency, the role price currency, and the base currency are three different things and they are frequently three different currencies. Ask the question before somebody presents a margin number to a board.
Prove it, then plan the first ninety days
From build through to hypercare
The last phase, and the one that decides whether the system is still trusted in month six.
Test at realistic volume, not against twenty demo rows
Wall four on this page explains why. A query written the wrong way against a large table returns an answer that is wrong rather than slow, and it looks perfect during testing precisely because the test data was small.
Write the regression list once, and retest it every release wave
Pricing logic, embedded apps, code components, the flows on your key records, and every integration. The list is short, it takes an hour to write, and it is the whole difference between a managed update and a surprise.
Enable the early release channel on the test environment
So you meet a release wave in a place where it does not matter. This is free, it takes one setting, and almost nobody does it.
Run acceptance testing with the people who will actually use it, against scripted scenarios
Real scenarios end to end, run by the users themselves, not a walkthrough delivered to them. A user who has driven their own record through the system before go live is a different person in week one.
Write the cutover runbook, including the rollback
What freezes and when, who signs off each step, what the last good state is, and how you get back to it. Written the week before, not the night of.
Budget hypercare, then a standing support allowance for year two
Concentrated support for the first weeks, then a steady allowance from around twenty hours a month for one Customer Engagement app. It is the line most often left out of a comparison between doing it yourself and hiring, and it applies to both.
Confirm the handover in writing before you sign anything
Source in a repository you own, solutions your own administrator can import, and documentation another developer could pick up. If a supplier cannot agree that at the start, the question of what happens at the end has already been answered.
Two of those phases assume you are starting from nothing. If a build already exists, do not work the list blind: a health check and technical audit tells you which of these decisions were already made for you and which were never made at all, and its findings are what should fill the checklist in. If the project has stalled outright, the project rescue and takeover service starts from the same place, with the forensic audit first and the week by week timeline that follows it.
The checklist is also a partner test. Hand it to each supplier on your shortlist and watch which items they answer with a process rather than a reassurance, particularly the environment, migration, and currency phases. Our post on how to choose the right D365 partner sets out the technical questions that predict delivery better than a badge or a reference call does, and the nine buying questions earlier on this page are the commercial half of the same conversation.
How does Solzet fit in?
Stated plainly, so you can hold it against doing it yourself or against another supplier.
CRM specialists, not a general software shop
On the Microsoft side we work on Dynamics 365 Customer Engagement and the Power Platform: Sales, Customer Service, Field Service, Customer Insights, Power Apps, Power Automate, Power Pages, Dataverse, and PCF code components in TypeScript and React. For organizations that want CRM without Microsoft licensing, we also build custom CRM on React, Node.js, PostgreSQL, and .NET. We do not implement Business Central or Finance and Operations, and we keep the scope narrow on purpose, because the walls on this page are only routine to a team that meets them every week. If what you need sits outside it, you will hear that at the first conversation rather than three weeks into a project.
Buy the part you need
Three engagement models: a dedicated resource on a three to twelve month contract, time and materials against a backlog, or a fixed price deliverable. A design review, one plug-in, one migration, or a full implementation are all normal sizes of work. We would rather scope the piece you cannot do than replace a team that is doing fine.
You own the result
Source in a repository you own, solutions your admin imports, and documentation good enough for another developer to pick the work up. We use your Azure DevOps, GitHub, or Jira and meet over Teams or Zoom. Contracts are B2B, with NDA, a GDPR compliant data processing agreement, and IP ownership set out in the statement of work.
Certified engineers, one time zone, three languages
We deliver from a single hub in Yerevan, Armenia, at GMT+4, which leaves roughly four to six hours of daily overlap with Western Europe and reaches into the US morning. Our engineers hold Microsoft certifications including PL-200, PL-400, and PL-600 for the Power Platform and MB-210, MB-230, and MB-240 for Dynamics 365 Customer Engagement, and we work in English, Armenian, and Russian.
The services themselves are described under Dynamics 365 Customer Engagement consulting and Power Platform consulting, and if you are a Microsoft partner rather than an end client, the same team works white-label under Dynamics 365 subcontracting. If the question behind the question is whether you need Microsoft licensing at all, we also build custom CRM without it, and we will tell you which route fits.
Кратко по-русски: реально ли без разработчика?
Во многом да. Формы, представления, бизнес-правила, бизнес-процессы, роли безопасности, дашборды и большинство облачных потоков Power Automate настраиваются без единой строки кода, и значительная часть внедрений Dynamics 365 действительно начинается именно так.
Разработчик становится необходим там, где заканчивается конфигурация: нестандартное ценообразование и скидки, которые не выражаются прайс-листом; SLA-правила сложнее статуса и календаря рабочего времени; миграция данных с сохранением связей, истории и вложений; большие объёмы записей, где перестаёт работать делегирование запросов в canvas-приложениях; интеграции с собственной аутентификацией и обработкой ошибок; разделение сред разработки, тестирования и продуктива с управляемыми решениями; продуманная модель безопасности; и собственные элементы интерфейса на PowerApps Component Framework.
Разумный вариант для большинства команд не «отдать всё подрядчику», а купить именно ту часть, которую невозможно сделать конфигурацией. Мы работаем из Еревана на английском, армянском и русском языках.
О бюджете. Мы не публикуем почасовые ставки. Ориентир по региону такой: армянская или грузинская компания с сертифицированными старшими инженерами обычно заметно дешевле подрядчиков из Центральной и Восточной Европы, а те, в свою очередь, дешевле западноевропейских и американских консультантов. Попросите у каждого подрядчика ставки по ролям после обсуждения объёма работ, а не сравнивайте опубликованные цифры. Чтобы получить бюджет проекта, умножьте ставку из полученных предложений на трудоёмкость по строкам в таблице выше: настройка стандартного приложения, миграция данных, каждая интеграция, каждый PCF-компонент, настройка сред и решений. Мы работаем по времени и материалам либо по фиксированной цене за этап, и всегда называем основу расчёта до подписания договора.
Расширять Dynamics 365 или делать отдельное приложение Power Apps? Расширяйте, когда речь идёт о записях, которые уже есть в Dynamics 365: клиенты, сделки, обращения, заказы на работы. Делайте отдельное приложение, когда у процесса свои собственные таблицы и своя аудитория: заявки на оборудование, осмотры объектов, анкеты поставщиков. Главное ограничение лицензионное: лицензия Power Apps даёт доступ к стандартным и вашим собственным таблицам Dataverse, но не к ограниченным таблицам Dynamics 365, и собственный экран этого не меняет. Держите оба решения в одной среде Dataverse, и интеграция между ними просто не понадобится.
Что сделать до старта внедрения. Ниже на этой странице есть чек-лист подготовки из девяти этапов: цели и владельцы процессов, три среды и управляемые решения, привязка ролей безопасности к владельцам процессов, очистка и дедупликация данных до миграции, описание каждой точки интеграции, а также то, что важно именно в нашем регионе. Базовая валюта Dataverse задаётся при создании базы и потом не меняется, курс валюты в системе статический и его кто-то должен обновлять, налоговая счёт-фактура в Армении и Грузии выписывается через государственную систему электронных счетов, а календари праздников и отсутствие перехода на летнее время влияют на расчёт SLA. Чек-лист можно скачать и открыть на печать.
What do teams ask about hiring a consultant vs DIY?
Can we really implement Dynamics 365 without a developer?
For a large part of a first implementation, yes. Tables, relationships, forms, views, business rules, business process flows, security roles, dashboards, and most Power Automate cloud flows are configuration, and a capable functional consultant or business analyst can deliver a working Sales or Customer Service app without writing code. What reliably requires a developer is a shorter list than most vendors imply: pricing and discount logic the price list cannot express, service level agreement behaviour beyond status and business hours, data migration that has to preserve relationships and history, real record volumes where canvas app delegation limits start returning wrong answers rather than slow ones, integrations that need their own authentication and retry handling, environment separation with managed solutions, and custom interface components built with the PowerApps Component Framework. The useful question is not whether you need a developer for the project. It is which of those walls your particular project actually hits.
Should we hire a Dynamics 365 consultant or do it in-house?
Draw the line by task type, not by budget. Configuration of tables and columns, view and form edits, simple business rules and most reporting belong with your own team once someone is trained, because they change often and are easy to undo. Plug-in development, solution architecture, Dataverse security redesign, ALM pipelines, data migration and anything touching a production cutover belong with an experienced delivery team, because mistakes there land in production and are expensive to reverse. Most organizations do best with both: an in-house owner for the everyday changes and a team brought in for the engineering work, with the source and documentation handed over as they go.
Is a freelancer from a marketplace a good choice for Dynamics 365 Customer Engagement work?
For a small, self contained task that someone in-house can review, it can be. For implementation work it usually fails in three predictable ways. There is no continuity, because the knowledge of your environment sits with one person who may move on. There is often no source control handover, so plug-in source, versioned solutions and documentation never reach a repository you own. And there is no accountability at cutover, because a milestone accepted in a sandbox carries no obligation to be present at go-live or through hypercare. A delivery team puts named people and a second reviewer on the work, delivers into your repository from the first day, and owns the cutover runbook through go-live.
Do we need a short engagement or an ongoing retainer with a Dynamics 365 partner?
Choose a short engagement when the work has a defined end state and testable acceptance, such as a migration, an ALM pipeline, a security redesign or a cutover, and your own team will own the result afterwards with knowledge transfer written into the scope. Choose a retainer when engineering grade changes arrive every month, when release waves and integrations need regular regression testing and monitoring, when nobody in-house can review code or own the deployment pipeline, or when the system is business critical and you need a known response path rather than a new search each time something breaks.
What is the first thing that usually forces a DIY Dynamics 365 project to hire someone?
In our experience it is pricing, and closely behind it, data migration. Dynamics 365 Sales price lists, price list items, and discount lists cover standard commercial models well, but as soon as pricing depends on a negotiated customer agreement, on what else is on the quote, on compounding tiers, or on a margin floor that has to block a save, configuration runs out. Sales anticipates this: the system pricing calculation can be switched off so a plug-in supplies the price instead. That is a supported extension point and it is also compiled code in your production environment, which is a different kind of commitment from a business rule. Migration forces the issue for a different reason: the import wizard works right up until rows have to resolve lookups, match rather than duplicate, and carry original dates and attachments across.
How do I know if my Power Platform build has already gone too far to fix myself?
The reliable signals are ownership and environment signals rather than technical ones. Changes are made directly in production because there is nowhere else to make them. Everything is in the default solution. Production flows and connections are owned by an individual account belonging to someone who has moved on. There is script on a form or a plug-in in the environment and nobody can say what it does. Users have quietly gone back to a spreadsheet for the part of the process the system was supposed to fix. Every new requirement starts with a workaround for a previous workaround. None of these mean the build is worthless, and most of what we take over is worth keeping. They do mean the next change costs more than the last one, and that curve does not flatten on its own.
Should we extend Dynamics 365 or build a separate Power App?
Extend when you are enhancing something that already exists as a Dynamics 365 record: adding fields, rules, a stage, or a screen to an account, a contact, an opportunity, a case, or a work order. The record, its security model, its service level agreements, and its reporting are already there, the users already hold the licence, and a separate app would have to reproduce all of it. Build separately when the process has its own records and its own audience: asset requests, site inspections, supplier onboarding, a fleet log, a safety checklist. Nothing in those is a restricted table, so occasional users can be licensed per app rather than per application, and the tables sit in a solution of your own with nothing underneath them that a release wave can move. Three things decide the borderline cases. First, licensing: a Power Apps licence does not reach the restricted tables that belong to a Dynamics 365 application, whatever you build over them. Second, release cadence: extending puts your work in a layer above Microsoft components that update twice a year, which makes regression testing a standing cost. Third, ownership: if the design ends with customer data living in two places, you have bought a synchronisation job permanently. Where you do build separately, keep it in the same Dataverse environment so it can look up the real account record rather than a copy of it.
Can a Power Apps licence be used instead of a Dynamics 365 licence?
Not for Dynamics 365 data. Power Apps licensing, whether per app or the Premium plan previously sold as per user, entitles a user to standard Dataverse tables and to the tables you create yourself. It does not entitle them to the restricted tables that belong to a Dynamics 365 application, which include cases, opportunities, quotes, orders, invoices, contracts, and work orders. Building your own canvas app, model driven app, or portal over those records does not change what the licence covers, because entitlement follows the table rather than the screen. So the plan that starts with building our own app so we do not have to license everyone ends in one of two places: buy the Dynamics 365 licence for the people who touch those records, or change the design so those people work with your own tables and a licensed user is the one who touches the Dynamics 365 record. There is a third answer that is often the cheapest and is routinely missed: an attach licence for a user who already holds a base application licence and needs a second application. If the audience is outside your organization, none of this applies and the answer is Power Pages, which is licensed by page views rather than by named internal users. And if the real goal is to avoid Microsoft licensing altogether rather than to reduce it, the honest route is not a workaround on Dataverse but a custom-built CRM on React, Node.js, PostgreSQL, or .NET, which carries no per user licence at the cost of building what the Dynamics 365 application would otherwise have given you. Check the current Microsoft licensing guide before you commit, because the price list moves and the entitlement detail is revised.
What does extending Dynamics 365 cost to maintain over the long term?
The recurring cost is regression testing, and it exists because your work shares a surface with a product that updates on a schedule you do not set. When you customize a component that ships in a Microsoft managed solution, your change becomes a layer above theirs rather than an edit to it. Your layer keeps winning, which is what you want, right up until the day the change underneath was the fix you needed. The solution layers view on a component tells you what is actually stacked on a form, and on an environment you have inherited it is usually the first honest picture anybody has had of it. The manageable version of this is a test environment with a realistic copy of the data, the early release channel enabled there, and a written list of what gets retested at each release wave: the pricing logic, any embedded canvas app, the code components, the flows on the case, and the integrations. That list is short and it is worth writing once. Building separately does not remove maintenance, it moves it. Your own tables have no Microsoft layer beneath them, but you now own the data model, the security model, the reporting, the connector versions, and the answer to who changes it when the person who built it moves on.
How do a Power App and Dynamics 365 work together without building an integration?
Put them in the same Dataverse environment. When a Power App and a Dynamics 365 application share an environment they share the tables, the security roles, the auditing, and the reporting, so there is no integration to build, nothing to synchronise, and no second copy of the customer list. Beyond that, three patterns cover most coexistence. A canvas app can be embedded on a model driven form with the current record passed into it, which suits a guided task or a phone shaped screen inside a record people already open, at the cost of a second artefact with its own connections and its own testing. A custom page belongs to the model driven app itself, opening full page or as a side dialog from the site map or a command, and for most of what people used to embed a canvas app for it is now the cleaner choice because it stays inside the app navigation and the app security. A PCF code component is right where the requirement is one interaction rather than an application, and it keeps everything inside the record and the solution. Use separate environments only where there is a real constraint such as a different data loss prevention boundary, a data residency requirement, or a genuinely different owner and release cadence. Short of that, separate environments mean an integration you have chosen to build and will have to monitor.
Is it cheaper to build it ourselves?
On the invoice, yes. The comparison people usually miss is that a do it yourself build spends the time of whoever understands the business best, taken from the job they were actually hired for, and that the expensive part of these projects is rarely the build. It is the rework: a data model changed after a year of records, a security model redesigned once a second business unit exists, a single environment split into three, an integration that has been quietly dropping records. A middle route is normally the best value. Keep the apps, flows, and model with your own people, and buy the specific pieces that are genuinely code, plus a design review early enough to matter. We do not publish fixed prices because scope drives everything, and we quote on time and materials or fixed price per milestone after a scoping conversation.
What does a Power Platform implementation typically cost in Armenia or the Caucasus?
Build the number rather than asking for it, because a typical project cost quoted without a scope is meaningless. Two inputs give you a defensible budget. The first is the rate, which depends mostly on where the team sits: an Armenian or Georgian consultancy with certified senior engineers offers competitive rates well below Central and Eastern European nearshore, which is itself below Western European and US consultancies and global systems integrators. Ask each shortlisted partner for a rate card by role after a scoping call rather than comparing published figures. The second input is effort. For a first Customer Engagement rollout, plan 5 to 12 engineer days for discovery and solution design, 15 to 35 for core configuration of one standard app, 10 to 30 for migrating one legacy system, 8 to 25 for each integration with a system that has no maintained connector, 5 to 15 for custom pricing logic as a plug-in, 5 to 20 for each PCF code component, 3 to 8 for environments, solutions, and a deployment pipeline, 2 to 6 for the security model, and 5 to 15 for training and hypercare. Multiply the effort by the rates in the proposals you receive, add licences separately, and budget from around 20 hours a month for support in year two. These are planning ranges from what we scope in this market, not a price list, so hold them against two or three real proposals.
Should we buy fixed price or time and materials for a Dynamics 365 project in the Caucasus?
Split the quote. Fixed price per milestone is correct where scope is genuinely knowable in advance, which covers discovery, environment and solution setup, and core configuration of a standard app. It transfers risk to the supplier, and you pay a premium for that, so ask for the assumptions behind the price as a numbered list: how many records are migrated, how many integration endpoints, how many custom components, how many user groups trained. Treat anything the list does not name as a change request and agree the change rate before signing. Time and materials against a backlog is correct for migration, integrations, and anything custom, because a fixed price on those is a guess with a margin attached, and it is cheaper for the same work since you are not buying the risk premium. Ask for a not to exceed ceiling per phase if finance needs a number. A dedicated resource on a three to twelve month contract is the third model and usually carries the lowest hourly rate, with the responsibility for keeping that person usefully busy sitting with you. A supplier who will not split a quote along those lines is telling you how well they understand your scope.
How do we evaluate a Dynamics 365 partner in Armenia or Georgia without a local reference network?
Ask nine things and judge the answers rather than the pitch. A rate card by role with day counts per line item, not a single blended number. Whether project management, QA, and account management are billed and at what proportion of build time, so you can compare proposals like with like. Which legal entity contracts, in what currency you are invoiced, and how VAT is handled, since regional consultancies commonly contract B2B and invoice in USD or EUR and an EU or UK buyer needs reverse charge confirmed. Whether the engineer you interview is the engineer who builds, and what cover exists for holiday, illness, and resignation, because the regional market is small and good engineers are portable. Which Microsoft certifications the delivery engineers hold, meaning PL-200, PL-400, and PL-600, and MB-210, MB-230, and MB-240. Who owns the source, the solutions, and the documentation, and where they live. How many hours of daily overlap you actually get and what the escalation path is. Whether the migration was scoped, which you test by seeing if they asked about record counts, attachments, duplicates, and history before quoting it. And whether they have taken over another supplier work before, which a partner who has done it will answer with a process rather than a reassurance. Apply all nine to us as well.
What can a citizen developer safely own long term?
The app layer and the process layer, provided the environment underneath them is set up properly by somebody who knows how. Forms, views, dashboards, business rules, business process flows, and most cloud flows are exactly what the maker tools were designed for, and a business owned team maintains them faster than an external supplier can. What should not sit with a single citizen developer is the environment strategy, the solution and deployment approach, the security model, anything holding compiled code, and any integration with an external system. The healthy pattern is a maker team that owns the everyday build on foundations a specialist laid, with a named person to call when a requirement crosses one of those lines.
Can you work with our internal team rather than taking the project over?
Yes, and it is a common arrangement. Your makers keep the model, the apps, and the flows, and we take the parts that are genuinely engineering: a pricing plug-in, an integration, a code component, a migration, or the environment and solution setup. We can also work the other way round, reviewing a design before anything is built or auditing what already exists and telling you plainly what is sound. Engagement models are a dedicated resource for three to twelve months, time and materials against a backlog, or a fixed price deliverable, whichever matches how you buy. The point of every one of them is that your team keeps ownership of your own system.
Our implementation has stalled. Do we start again?
Usually not. Most stalled implementations contain a large amount of work worth keeping, and the problem is a specific set of decisions rather than the whole build. The first step is an honest assessment: requirements and process fit, how the standard modules are configured, the state of the customizations and code, security and data quality, integrations, platform health, and who actually owns delivery. That produces a list of what is fine, what needs work, and what has to be rebuilt, with an estimate against each. Only then is starting again a decision anybody can make with information. We run this as a named rescue and takeover service, including on environments originally built by another supplier.
What should we do before starting a Dynamics 365 implementation?
Settle nine things, and settle them on paper before anybody opens a maker portal. One, the outcome in a single sentence and the measure that proves it, plus a named sponsor and a named decision maker per process. Two, environments: development, test, and production as separate environments, your own publisher and solution rather than the default one, managed solutions into test and production, source in a repository you own, a data loss prevention policy set before the makers arrive, and the Dataverse region and base currency chosen at creation because neither can be changed afterwards. Three, security: list every process, put one owner name against it, design business units around how records must be separated rather than around the org chart, decide user or team ownership per table before any record exists, and decide who can export to Excel and who can bulk delete. Four, data: count the rows per source table, decide the history cut off explicitly, pick the one canonical customer list, deduplicate on a defensible key such as a tax identification number, create alternate keys on the legacy identifier so a reload updates rather than duplicates, and rehearse the migration at full volume. Five, integrations: one page listing every endpoint with direction, trigger, volume, field mapping, authentication owned by a service principal rather than a person, an idempotency key, a retry policy, and a named human who is alerted on failure. Six, currency and tax. Seven, local compliance and calendars. Eight, Project Operations decisions if projects are in scope. Nine, testing at realistic volume, a written regression list, a cutover runbook with a rollback, and a support budget for year two. The full version of all nine phases, with 66 checkpoints, is on this page and downloadable as a print ready page.
What is different about a Dynamics 365 implementation checklist for Armenia or the Caucasus?
Four things that a generic implementation checklist has no reason to carry. First, currency. Regional projects routinely contract in US dollars or euros, report statutorily in Armenian dram or Georgian lari, and invoice in a third currency, and the Dataverse base currency is fixed when the database is created and cannot be changed afterwards, so choosing it wrong means a new environment and a full migration. The exchange rate on a currency record is also a static number somebody has to maintain, with no automatic feed, and base currency amounts are calculated with the rate in force when each record was written, so a base currency total is a mixture of historical rates rather than a restatement. Agree with finance what that report means before the first board pack. Second, the fiscal invoice. In Armenia and Georgia the tax invoice is issued through the state electronic invoicing system, so Dynamics 365 is the commercial record and not the fiscal one on almost every regional project. Decide which field carries the reference between the two, and model VAT treatment as a field on the account covering domestic supply, export of services, and reverse charge for EU business customers. Third, calendars. Armenian, Georgian, and Azerbaijani public holidays are three different lists and none of them match a default calendar, and Armenia does not observe daylight saving, so the working overlap with European customers moves by an hour twice a year. Both affect SLA clocks and support windows. Fourth, data quality: the same organization commonly exists once in Armenian or Georgian script and again in Latin transliteration, so name based duplicate matching silently creates two customers, and a tax identification or registration number is the only matching key worth relying on.
How do we map Dynamics 365 security roles to process owners?
Start from the processes rather than from the roles. Write out every process the system will carry, such as quote approval, case escalation, discount authorisation, project contract sign off, and credit hold, and put exactly one person name against each. Then design business units around how records genuinely have to be separated rather than around the reporting structure, because the org chart changes every year and the separation requirement rarely does. For each table, decide user ownership or team ownership before any record exists: records owned by a person disappear from view when that person leaves, records owned by a team survive it, and changing your mind later means moving every row rather than editing a permission. Only then build the security roles, writing out create, read, write, delete, append, append to, assign, and share at the depth you actually mean, and saying in the same document why anything is set to organization wide. Add field level security for the short list of columns that need it, typically cost, margin, discount ceiling, day rate, and personal data. Decide manager visibility deliberately, choosing between hierarchy security, a wider business unit, or a team, since all three have different maintenance costs. Finally, agree explicitly who can export to Excel and who can run a bulk delete, and write down what happens when somebody leaves, including reassignment of records, of flows, and of connections. None of this needs code, which is precisely why it gets left, and ownership and business unit changes are expensive later because they move records rather than just permissions.
Can we implement volume based discounts in Dynamics 365 without code?
Often yes, and the answer depends on one question: what the tier is measured on. If the tier is a quantity band on a single quote line, a table scoped business rule on Quote Line does it. Add a condition on Quantity, add a Set Field Value action on Manual Discount Amount using a formula built from Quantity and Price Per Unit, add a branch per tier, activate it, and test with an import file as well as with the form. If the tier depends on the whole order, on several lines of the same product added together, on a value rather than a count, on a validity date, or on a customer agreement, business rules cannot express it, because a rule only reads columns on the row being saved. That case is a Power Automate cloud flow over a custom Discount Tier table: trigger on Quote Lines, list the sibling lines to compute the aggregate, match a tier row, write the Manual Discount Amount, and stamp a calculated on column so the flow does not retrigger itself. The limit of the flow route is that it is asynchronous, so it cannot guarantee the number at the instant of the save and cannot block one. Once a margin floor has to stop a save, or the seller has to see the tier update while typing, you are into a plug-in and a code component, which is developer work.
Do we need a PCF control or a CPQ product for tiered pricing in Dynamics 365 Sales?
A custom PCF control is justified by one requirement, which is a live calculation the user sees before saving that depends on more than the line in front of them. A code component can read the other lines and the tier configuration through the Dataverse Web API and recalculate as the quantity is typed, which neither a business rule nor a flow can do. It has to be paired with server side enforcement, because a control runs in the browser and is bypassed by an import or an integration, so a control on its own gives a convincing demonstration rather than a correct database. Note that a control such as our free String Calculator is a different thing again: it composes text from other columns, so it is useful for showing which tier and which agreement produced a discount, not for calculating it. A configure price quote product is the right call once the requirement stops being a discount rule and becomes a pricing system: configurable products with compatibility rules, bundles and kits priced as a unit, guided selling, subscription ramps and proration, renewal uplifts, and a multi level approval matrix. The test we use is whether the way you price is a competitive advantage worth owning or complexity you would rather not maintain. The first is a build, the second is a purchase plus an integration.
How do you make Dynamics 365 calculate a discount automatically based on order volume?
Start by deciding how fresh the number has to be, because that single answer picks the layer and almost every argument about volume pricing is that question left unasked. If the figure can be up to an hour old, it is pure configuration and needs no developer: add a rollup column on the quote header that sums Quantity, or the line amounts, across the quote lines, then a calculated column on the line whose condition reads that parent rollup and returns the tier. Both are computed and read only, so use them for the tier badge on the form, views a manager filters, approval conditions and reporting. If the discount itself has to be written, meaning the quote total has to move, something that can write must copy the figure into Manual Discount Amount, because Manual Discount Amount is a system column and cannot be made calculated. A table scoped business rule does that where the whole calculation sits on one line. A Power Automate cloud flow over a custom Discount Tier table does it where the tier is measured across lines, on a value rather than a count, or against validity dates, at the cost of the number settling a few seconds after the save. If the number has to be correct at the instant of the save whatever wrote the row, including an import file or an integration, that is a synchronous plug-in registered pre-operation on the quote line, and it is the only one of these routes that is genuinely developer work.
Can a calculated field or a rollup field handle volume based pricing in Dynamics 365 Sales?
They handle the measurement, never the money. A rollup column on the quote header is the cheapest way to get the order volume figure a tier is measured on, with no code at all, and a calculated column on the quote line can read that parent value through the lookup and return the band it falls into. Two limits decide how far that gets you. First, rollup columns recalculate on an asynchronous system job rather than inside the save, hourly at the fastest plus an on demand refresh, so the figure is reporting grade and cannot be the basis of a price a seller sees immediately. Second, and more decisive, both column types are computed and read only: the pricing engine does not consult them, the header totals do not move when they change, and Manual Discount Amount is a system column that cannot be redefined as calculated. So a calculated column can show that a line qualifies for tier three and can drive an approval condition or a view, and it can never be the discount. Something that can write, meaning a business rule, a flow, or a plug-in, still has to put the amount in the writable column.
Реально ли внедрить Dynamics 365 без разработчика?
Во многом да. Формы, представления, бизнес-правила, бизнес-процессы, роли безопасности, дашборды и большинство облачных потоков Power Automate настраиваются без кода, и значительная часть первого внедрения действительно делается силами функционального специалиста. Разработчик нужен там, где заканчивается конфигурация: нестандартное ценообразование и скидки, которые не выражаются прайс-листом и требуют плагина; SLA-правила сложнее статуса и календаря рабочего времени; миграция данных с сохранением связей, истории и вложений; большие объёмы записей, где перестаёт работать делегирование запросов; интеграции с собственной аутентификацией и обработкой ошибок; разделение сред и управляемые решения; и собственные элементы интерфейса на PowerApps Component Framework. Solzet работает из Еревана на английском, армянском и русском языках, и мы одинаково спокойно берём как отдельный кусок работы, так и внедрение целиком.
We recommend the right solution - whether that's Microsoft Dynamics 365, Power Platform, or a custom-built CRM. Some businesses need the Microsoft ecosystem. Others need full control without licensing. We deliver both.
Not sure which side of the line you are on?
Describe the process, the volumes, and what you have built so far. You will get a straight answer about which parts are configuration your own team can own and which parts are genuinely engineering, and a scope for only the second list. Solzet delivers Dynamics 365 Customer Engagement, Power Platform, and custom CRM work from Yerevan, Armenia, to clients and Microsoft partners across Europe and the US.