A consultancy ships a feature to production by exporting an unmanaged solution from dev and importing directly. It works for the demo. Six months later the production environment has eight unmanaged layers, conflicting customizations, and no clear path to roll back the latest change. Solution discipline is the difference between an environment you can evolve and one you have to rebuild.
Managed vs Unmanaged
Unmanaged: edit anything, solution is a grouping. Managed: installed as a unit, fields and tables cannot be edited. Ship managed to production. The managed-to-production rule is the single most important ALM discipline; without it, every production change is a hand-edit and your environment drifts away from source control.
Managed solution traits:
- Components cannot be edited in target environment
- Updates apply via re-import of new version
- Removal cleans up all components
- Layer position determines override behavior
Unmanaged solution traits:
- Components are editable
- Removal does not clean up
- Suitable for development only
Solution Layering
Multiple managed solutions layer on top of each other. Conflicts resolve by layer order. Plan layering — hotfix layer above everything, customer-specific layer at the top. The layer model means a hotfix solution can override a base solution without modifying the base.
Standard layer order (top to bottom):
1. Customer-specific overrides
2. Hotfix layer
3. Feature solutions
4. Core platform solution
5. ISV solutions
6. Default Dynamics 365 components
Document the layer order on the wiki so the next admin does not invert it.
Azure DevOps Pipelines
Power Platform Build Tools provide tasks: export solution, pack, unpack, publish, import. Git-tracked solution zip is the deliverable. Fully automatable. The pipeline shape that works is build-from-source on commit, deploy-on-approval to staging, deploy-on-approval to production.
- task: PowerPlatformExportSolution@2
inputs:
Environment: $(devEnvironment)
SolutionName: ContosoCRM
SolutionOutputFile: $(Build.ArtifactStagingDirectory)/ContosoCRM.zip
Managed: true
- task: PowerPlatformImportSolution@2
inputs:
Environment: $(prodEnvironment)
SolutionInputFile: $(Build.ArtifactStagingDirectory)/ContosoCRM.zip
AsyncOperation: true
MaxAsyncWaitTime: 60
The async operation is non-optional for production; long imports otherwise time out the pipeline.
Git plus Source Tree
pac solution unpack exposes solution as a file tree. Diff is readable. Pull requests on Dataverse customization become realistic. The unpacked tree contains XML files per component; reviewers can read the diff in plain text and comment on specific changes.
Solution unpack output:
src/
Entities/
Account/
Forms/
Views/
Attributes/
Contact/
WebResources/
Workflows/
PluginAssemblies/
Commit the unpacked tree, not the zip. The zip is a build artifact; the source tree is the source of truth.
Staging Environments
Dev to Test to Staging to Prod. Each environment has a distinct purpose. Do not conflate dev and staging; you will regret it. Dev is where makers experiment; staging is where the production-bound build runs end-to-end with production-like data.
Environment purposes:
- Dev: maker workspace, frequent rebuilds, throwaway data
- Test: integration testing, automated regression
- Staging: pre-prod validation, prod-like data, change advisory
- Prod: live, managed-only, no in-place edits
Connection References and Environment Variables
Solutions that include flows must use connection references; flows that reference connections directly cannot be deployed across environments. Environment variables hold per-environment values (URLs, IDs) so the same solution package works everywhere.
solution.xml includes:
- ConnectionReferences with logical names
- EnvironmentVariables with default and current values
deployment maps:
- Per-environment connection mapping
- Per-environment variable values
Solution Patches vs Versions
Patches add components to a parent solution; versions replace the parent entirely. Use patches for hotfixes between major releases; use versions for normal release cadence. Patches stack and can become hard to reason about; merge them into the parent during the next major version.
What to do this week
Audit your environment for unmanaged components in production, build the pipeline from a clean dev export, and start using connection references on every new flow. Document the layer order for the next admin and require pull requests for solution changes.