[object Object]

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.

[object Object]
Share