SysObsolete is an X++ attribute used to mark classes, methods, fields, or enums as deprecated. It signals to developers that an element should no longer be used and may be removed or replaced in a future release. When applied, the compiler emits warnings (or errors, depending on severity) whenever the obsolete element is referenced, guiding refactoring toward the recommended alternative. SysObsolete is a key mechanism for managing technical debt, ensuring forward compatibility, and enforcing controlled deprecation without breaking existing code immediately.
In the codebase, these attributes typically appear directly on the artifact itself, making their intent explicit at compile time.

I did a small count using Agent Ransack and found 3,994 methods marked as obsolete. I fully understand that Microsoft must account for customers, partners, and ISVs that still rely on parts of this surface area. That said, the cleanup process is objectively slow. We still have code that has been obsolete for more than a decade, which indicates a systemic issue rather than a temporary compatibility concern.
According to Microsoft documentation, obsolete methods may be deleted unless telemetry shows that they are still being used. If telemetry indicates usage, Microsoft will not remove them in order to reduce the risk of breaking consumers. This is an important detail: the presence of obsolete code is not the real problem — continued usage is. As long as deprecated APIs are still invoked in customer or partner solutions, Microsoft is effectively blocked from removing them.
Microsoft therefore recommends compiling your codebase against the latest application and platform versions at least every 12 months. Any warnings caused by deprecated or obsolete artifacts should be addressed as soon as possible. In practice, these warnings should not be treated as background noise. They are an explicit signal that technical debt is being carried forward.
This leads to an uncomfortable but necessary conclusion: a significant reason obsolete code remains in the platform is that customers, partners, and ISVs are not acting on compile warnings. If obsolete APIs continue to show up in telemetry, Microsoft cannot safely remove them — regardless of how old or redundant they are.
As a community, we should take more responsibility here. Cleaning up our own code and removing dependencies on obsolete APIs makes the platform healthier for everyone. When telemetry no longer shows usage, Microsoft can finally complete the deprecation cycle. This is one of the few areas where individual discipline directly enables platform progress.
The same reasoning applies to flights and feature flags. A quick scan shows 8,914 classes ending with *Flight, many of which are enabled by default today. Flights serve an important purpose during controlled rollouts and experimentation, but once a flight is globally enabled and has proven stable, it has effectively completed its lifecycle.
At that point, it should enter a formal deprecation path. Permanently enabled flights that remain in the execution path add:
- Cognitive overhead for developers
- Runtime condition checks
- Upgrade and refactoring complexity
In many cases, they have simply become technical debt. While each individual check may be cheap, the cumulative cost across the platform is not zero. Every conditional branch executed thousands or millions of times per day matters.
The same applies to features that are now considered part of the core behavior. If something must remain configurable for business reasons, it should be expressed as a parameter, not as a flight or feature flag. Flights are a rollout mechanism — not a permanent configuration model.
None of this ignores the realities of backward compatibility or long customer upgrade cycles. Microsoft is right to be cautious. Telemetry-based decisions are safer than forced breaking changes. But that caution only works if the ecosystem does its part.
AI and Copilot will help us write more code. They will not reduce the long-term cost of carrying unnecessary code forever. D365 will be delivered, extended, and maintained for many years to come. If we want it to remain performant, understandable, and evolvable, we need to treat deprecation as a process that actually completes — not as a warning we learn to ignore.
Pingback: How to Use AI to Understand What a Parameter Does in D365 Finance - dyn365.wiki