<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Oliver Fries</title>
    <description>The latest articles on DEV Community by Oliver Fries (@oliver_fries_dotnet_legacy_exp).</description>
    <link>https://dev.to/oliver_fries_dotnet_legacy_exp</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3443484%2Faebbc6ee-6eef-4c8f-b261-cf1d9df46b5c.png</url>
      <title>DEV Community: Oliver Fries</title>
      <link>https://dev.to/oliver_fries_dotnet_legacy_exp</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/oliver_fries_dotnet_legacy_exp"/>
    <language>en</language>
    <item>
      <title>The Digital Product Passport Is Moving From Concept to Execution</title>
      <dc:creator>Oliver Fries</dc:creator>
      <pubDate>Wed, 25 Feb 2026 07:41:21 +0000</pubDate>
      <link>https://dev.to/oliver_fries_dotnet_legacy_exp/the-digital-product-passport-is-moving-from-concept-to-execution-3e3</link>
      <guid>https://dev.to/oliver_fries_dotnet_legacy_exp/the-digital-product-passport-is-moving-from-concept-to-execution-3e3</guid>
      <description>&lt;p&gt;For a long time, the Digital Product Passport felt theoretical.&lt;/p&gt;

&lt;p&gt;Standards discussions. Working groups. Position papers.&lt;/p&gt;

&lt;p&gt;Now it’s different.&lt;/p&gt;

&lt;p&gt;Budgets are allocated. Platforms are being selected. Pilot projects are turning into implementation roadmaps. The question is no longer &lt;em&gt;if&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;It’s:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How do we actually deliver this in a real system landscape?&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  The Standard Is Not the Hard Part
&lt;/h2&gt;

&lt;p&gt;The Digital Product Passport builds on the Asset Administration Shell.&lt;/p&gt;

&lt;p&gt;The specification is detailed.The semantic structure is defined.&lt;br&gt;&lt;br&gt;
Interoperability is a serious effort. But in industrial reality, the friction is rarely the standard itself.&lt;/p&gt;

&lt;p&gt;It’s this:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Product master data in ERP
&lt;/li&gt;
&lt;li&gt;Technical attributes in legacy .NET systems
&lt;/li&gt;
&lt;li&gt;Bills of material in PLM
&lt;/li&gt;
&lt;li&gt;Units that differ between systems
&lt;/li&gt;
&lt;li&gt;Field names that evolved over fifteen years
&lt;/li&gt;
&lt;li&gt;“Digital” processes that still rely on Excel exports
&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;You don’t “introduce AAS” into that environment.&lt;br&gt;
You extract data from brownfield systems.&lt;br&gt;&lt;br&gt;
You map fields to semantics.&lt;br&gt;&lt;br&gt;
You normalize units.&lt;br&gt;&lt;br&gt;
You validate mandatory elements.&lt;br&gt;&lt;br&gt;
You automate the process.&lt;/p&gt;

&lt;p&gt;That is the actual work.&lt;/p&gt;




&lt;h2&gt;
  
  
  Platforms Are Being Bought. The Integration Layer Is Missing.
&lt;/h2&gt;

&lt;p&gt;Many companies are currently evaluating or purchasing DPP platforms.&lt;/p&gt;

&lt;p&gt;That step makes sense.&lt;/p&gt;

&lt;p&gt;But a platform does not create structured data where none exists.&lt;/p&gt;

&lt;p&gt;The real gap is not on the visualization layer. It is on the delivery layer.&lt;/p&gt;

&lt;p&gt;What the industry needs now are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Mapping libraries
&lt;/li&gt;
&lt;li&gt;Validation mechanisms
&lt;/li&gt;
&lt;li&gt;Deterministic submodel builders
&lt;/li&gt;
&lt;li&gt;CI-integrated generation processes
&lt;/li&gt;
&lt;li&gt;Clear ownership of source fields
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Not more slides.&lt;/p&gt;

&lt;p&gt;Engineering-grade building blocks.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why Open Source Matters at This Stage
&lt;/h2&gt;

&lt;p&gt;DPP is becoming infrastructure. Infrastructure should not depend entirely on opaque vendor logic.&lt;/p&gt;

&lt;p&gt;If regulatory compliance depends on generated submodels, then teams need to know:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Where each value comes from
&lt;/li&gt;
&lt;li&gt;How it is transformed
&lt;/li&gt;
&lt;li&gt;Which rules validate it
&lt;/li&gt;
&lt;li&gt;How it is versioned
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Open source enables that transparency.&lt;/p&gt;

&lt;p&gt;You can inspect it.&lt;br&gt;&lt;br&gt;
You can test it.&lt;br&gt;&lt;br&gt;
You can adapt it to your landscape.&lt;/p&gt;

&lt;p&gt;When regulation meets software delivery, black boxes become risk factors.&lt;/p&gt;




&lt;h2&gt;
  
  
  I Built FluentAAS
&lt;/h2&gt;

&lt;p&gt;FluentAAS was not created to “explain AAS.”&lt;/p&gt;

&lt;p&gt;It was created to build it.&lt;/p&gt;

&lt;p&gt;In real .NET environments. With legacy systems. Under delivery pressure.&lt;/p&gt;

&lt;p&gt;I needed a way to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Build submodels in a structured, typed manner
&lt;/li&gt;
&lt;li&gt;Encapsulate mapping logic in code
&lt;/li&gt;
&lt;li&gt;Validate mandatory fields early
&lt;/li&gt;
&lt;li&gt;Integrate generation into CI/CD
&lt;/li&gt;
&lt;li&gt;Version output alongside application releases
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;FluentAAS follows a simple idea:&lt;/p&gt;

&lt;p&gt;If DPP becomes part of compliance, submodels must be reproducible artifacts. Not manual exports.&lt;/p&gt;

&lt;p&gt;It is not a platform. It is not a full DPP solution. It is a building block.&lt;/p&gt;

&lt;p&gt;Because the ecosystem needs composable components, not monolith tools.&lt;/p&gt;




&lt;h2&gt;
  
  
  Legacy Is Not the Problem
&lt;/h2&gt;

&lt;p&gt;There is still a reflex in many discussions:&lt;/p&gt;

&lt;p&gt;“DPP means we need a new architecture.”&lt;/p&gt;

&lt;p&gt;In most industrial environments, that is not realistic.&lt;/p&gt;

&lt;p&gt;Legacy systems often contain the most reliable production data in the company.&lt;/p&gt;

&lt;p&gt;The real issue is uncontrolled integration.&lt;/p&gt;

&lt;p&gt;Rewriting a production-critical .NET system to “enable DPP” introduces risk without solving the mapping problem.&lt;/p&gt;

&lt;p&gt;You stabilize first. You define clear boundaries. You build a controlled extraction layer.  &lt;/p&gt;

&lt;p&gt;Then you map and validate into AAS.&lt;/p&gt;

&lt;p&gt;Legacy is not replaced. It is integrated under control.&lt;/p&gt;




&lt;h2&gt;
  
  
  What a Serious AAS Pipeline Requires
&lt;/h2&gt;

&lt;p&gt;If DPP becomes regulatory infrastructure, the pipeline must be:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Deterministic
&lt;/li&gt;
&lt;li&gt;Reproducible
&lt;/li&gt;
&lt;li&gt;Automated
&lt;/li&gt;
&lt;li&gt;Versioned
&lt;/li&gt;
&lt;li&gt;Validated
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That means:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Clear source ownership per field
&lt;/li&gt;
&lt;li&gt;Explicit transformation logic
&lt;/li&gt;
&lt;li&gt;Unit normalization at a defined boundary
&lt;/li&gt;
&lt;li&gt;Mandatory field validation before export
&lt;/li&gt;
&lt;li&gt;CI-integrated generation
&lt;/li&gt;
&lt;li&gt;Traceable versioning tied to product state
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you cannot regenerate the same submodel for the same product version tomorrow, you do not have compliance-grade infrastructure.&lt;/p&gt;

&lt;p&gt;You have a snapshot.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Shift That Is Happening
&lt;/h2&gt;

&lt;p&gt;The conversation is slowly changing.&lt;/p&gt;

&lt;p&gt;From:&lt;/p&gt;

&lt;p&gt;“How do we understand the standard?”&lt;/p&gt;

&lt;p&gt;To:&lt;/p&gt;

&lt;p&gt;“How do we build the integration layer?”&lt;/p&gt;

&lt;p&gt;That shift is necessary.&lt;/p&gt;

&lt;p&gt;It requires engineers.&lt;br&gt;&lt;br&gt;
It requires discipline.&lt;br&gt;&lt;br&gt;
It requires real tooling.&lt;/p&gt;

&lt;p&gt;The DPP ecosystem will mature through libraries, SDKs, validation tools and working pipelines.&lt;/p&gt;

&lt;p&gt;Not through architecture diagrams alone.&lt;/p&gt;




&lt;h2&gt;
  
  
  Closing Thought
&lt;/h2&gt;

&lt;p&gt;Momentum is real.&lt;/p&gt;

&lt;p&gt;Now the industry needs delivery capability.&lt;/p&gt;

&lt;p&gt;The Digital Product Passport will not be implemented by strategy documents.&lt;/p&gt;

&lt;p&gt;It will be implemented by engineers who take responsibility for the last mile:&lt;br&gt;&lt;br&gt;
From legacy data to validated, reproducible AAS submodels.&lt;/p&gt;

&lt;p&gt;If you are building in this space, focus on the pipeline.&lt;/p&gt;

&lt;p&gt;That is where success or failure will be decided.&lt;/p&gt;

</description>
      <category>dotnet</category>
      <category>opensource</category>
      <category>architecture</category>
      <category>digitalproductpass</category>
    </item>
    <item>
      <title>The Core Knowledge Every Senior C#/.NET Developer Must Master in 2026</title>
      <dc:creator>Oliver Fries</dc:creator>
      <pubDate>Thu, 19 Feb 2026 08:52:18 +0000</pubDate>
      <link>https://dev.to/oliver_fries_dotnet_legacy_exp/the-core-knowledge-every-senior-cnet-developer-must-master-in-2026-5lm</link>
      <guid>https://dev.to/oliver_fries_dotnet_legacy_exp/the-core-knowledge-every-senior-cnet-developer-must-master-in-2026-5lm</guid>
      <description>&lt;p&gt;$20,000 per hour. That's what one misconfigured garbage collection setting cost a manufacturing client of mine — not because the code was wrong, but because nobody on the team understood what the runtime was doing beneath the surface.&lt;/p&gt;

&lt;p&gt;The application worked fine in dev. It passed all tests. It even survived staging. But under real production load — 4,000 requests per second hitting a high-throughput API — GC pauses started cascading, response times spiked, and the production line ground to a halt.&lt;/p&gt;

&lt;p&gt;The fix took 45 minutes. Finding someone who understood the problem took three weeks.&lt;/p&gt;

&lt;p&gt;This is the gap I keep seeing when companies ask me to assess their senior .NET developers. They can write clean code. They know dependency injection. They use async/await correctly. But when things break at scale — when the runtime, the network, or the database pushes back — they're out of their depth.&lt;/p&gt;

&lt;p&gt;So here's what actually separates a senior C#/.NET developer from a mid-level one in 2026. Not more syntax. Not more frameworks. The deep, structural knowledge that makes the difference between code that works and systems that survive.&lt;/p&gt;

&lt;h2&gt;
  
  
  Runtime and Memory — Stop Fighting the CLR, Start Mastering It
&lt;/h2&gt;

&lt;p&gt;Junior developers write code. Senior developers understand how that code behaves inside the runtime. That distinction sounds abstract until your API starts dropping requests because Gen 2 collections are pausing your threads for 200 milliseconds.&lt;/p&gt;

&lt;p&gt;A senior .NET developer in 2026 needs to understand generational garbage collection — not as a textbook concept, but as an operational reality. Gen 0, Gen 1, Gen 2, ephemeral segment promotion, Large Object Heap fragmentation, Server GC vs Workstation GC trade-offs. These aren't academic exercises. They directly impact your p99 latency under load.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The developer who can read a GC trace and explain why throughput dropped at 3 AM is worth more than ten developers who can implement a clean repository pattern.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;And it doesn't stop at garbage collection. Allocation-aware async programming is now essential. Knowing the difference between &lt;code&gt;ValueTask&amp;lt;T&amp;gt;&lt;/code&gt; and &lt;code&gt;Task&amp;lt;T&amp;gt;&lt;/code&gt; isn't trivia — it's a performance architecture decision in async-heavy endpoints. Most mid-level developers use async. Seniors measure allocation pressure and optimize for it. They know about hidden allocations in async state machines. They use pooling patterns where it matters.&lt;br&gt;
Then there's zero-copy processing. &lt;code&gt;Span&amp;lt;T&amp;gt;&lt;/code&gt;, &lt;code&gt;Memory&amp;lt;T&amp;gt;&lt;/code&gt;, &lt;code&gt;ArrayPool&amp;lt;T&amp;gt;&lt;/code&gt; — these aren't niche tools for framework authors anymore. If your service parses JSON, processes streams, or handles binary protocols, zero-copy patterns are the difference between writing parsing code and writing infrastructure that scales.&lt;/p&gt;

&lt;p&gt;Here's the thing: none of this shows up in a typical coding interview. And that's exactly why so many teams discover these gaps in production.&lt;/p&gt;

&lt;h2&gt;
  
  
  Advanced C# Mastery — Beyond Syntax to Architectural Leverage
&lt;/h2&gt;

&lt;p&gt;Modern C# (12+) isn't about syntactic sugar. Every feature worth mastering is an architectural lever.&lt;/p&gt;

&lt;p&gt;Take source generators. Reflection is expensive — at runtime, it's slow; at scale, it's a bottleneck. Senior developers don't just avoid reflection. They replace it. They write source generators for validation, generate serializers at compile time, and eliminate entire categories of runtime overhead. In 2026, compile-time code generation is a performance architecture decision, not a nice-to-have.&lt;/p&gt;

&lt;p&gt;Default interface methods are another area where the gap shows. For teams maintaining SDKs or public APIs, understanding API evolution without breaking changes — including conflict resolution in interface hierarchies and the difference between virtual and static dispatch — is essential. Mid-level developers see it as a language feature. Seniors see it as a versioning strategy.&lt;/p&gt;

&lt;p&gt;Immutability isn't aesthetic — it prevents concurrency bugs in distributed systems before they ever reach production. Required members, init properties, primary constructors, records with domain semantics — these aren't about writing prettier code. In a distributed system where multiple services touch the same data, immutable objects are your cheapest concurrency safeguard. I've watched teams spend weeks debugging race conditions that simply couldn't exist with properly designed immutable aggregates.&lt;/p&gt;

&lt;h2&gt;
  
  
  Architecture — Designing for Change, Not Just Compilation
&lt;/h2&gt;

&lt;p&gt;This is where the mid-to-senior gap becomes a canyon.&lt;/p&gt;

&lt;p&gt;Senior engineers don't "add services." They design consistency boundaries. They think about where transactions end, where eventual consistency begins, and what happens when a message gets delivered twice.&lt;/p&gt;

&lt;p&gt;Clean Architecture with vertical slices has largely replaced the old layered monolith approach — feature folders, MediatR pipelines with behaviors, avoiding anemic domain models. The goal isn't architectural purity. It's enabling change without ripple effects.&lt;br&gt;
DDD aggregates matter here, but not as an abstract pattern. &lt;/p&gt;

&lt;p&gt;Aggregates define transactional limits. Domain events flow inside the boundary. Invariants are enforced through construction. If your "aggregate" is just a fancy name for an entity, you've missed the point.&lt;/p&gt;

&lt;p&gt;And then there's the pattern that separates production-grade systems from demo-grade ones: Inbox/Outbox with idempotency. Reliable message publishing, deduplication tokens, handling at-least-once delivery semantics. This is where many mid-level designs collapse in production. They work perfectly until the network hiccups, a message gets delivered twice, and suddenly your customer has been charged three times.&lt;/p&gt;

&lt;p&gt;One more thing I see senior developers get right: modular monoliths as a strategic scaling step. Before microservices, before Kubernetes, before the complexity explosion — deployable modules, internal ABI contracts, gradual extraction strategy. Premature distribution is a senior anti-pattern. The best architects I've worked with over 17 years know when not to distribute.&lt;/p&gt;

&lt;h2&gt;
  
  
  Performance Engineering — Measurement Over Guessing
&lt;/h2&gt;

&lt;p&gt;Performance in 2026 is no longer optional. It's expected. And "it feels fast" is not a measurement.&lt;/p&gt;

&lt;p&gt;With .NET 10, Native AOT and IL trimming are production-ready tools. Startup time reductions of 50%+ are achievable. But seniors understand the trade-offs: reflection limitations under AOT, ILLink trimming behavior, and when AOT is appropriate versus when it breaks dynamic systems. Not every service should be AOT-compiled. Knowing when to use it is the skill.&lt;/p&gt;

&lt;p&gt;Profiling the runtime is a core senior competency. dotnet-trace, tiered compilation analysis, JIT inline decision insights, GC pause diagnostics — not just "it's slow," but why it's slow. I've seen teams spend days adding caching to "fix" performance issues that were actually caused by oversized Gen 2 collections. They were optimizing the wrong layer entirely.&lt;br&gt;
Most mid-level developers know EF Core works. Seniors know how EF Core fails under load. Split queries vs single queries, ILazyLoader pitfalls, N+1 detection, owned types, projections, keyless entities, second-level caching strategies — this is where database performance lives or dies. The gap between "it works in dev" and "it scales in production" is filled entirely with this kind of knowledge.&lt;/p&gt;

&lt;h2&gt;
  
  
  Distributed Systems — Because That's the Default Now
&lt;/h2&gt;

&lt;p&gt;Microservices, event-driven architectures, cloud-native deployments — distributed systems aren't a specialization anymore. They're the default.&lt;/p&gt;

&lt;p&gt;Message-driven architecture with MassTransit sagas, long-running workflow orchestration, correlation IDs, idempotent consumers — this is production infrastructure. Not simplistic background job queues. The difference matters when your order processing pipeline handles 50,000 events per hour and one consumer crashes mid-saga.&lt;br&gt;
Ordered and reliable messaging adds another layer. Azure Service Bus sessions, optimistic concurrency with RowVersion, saga state persistence strategies. These patterns aren't optional when business logic depends on message order.&lt;/p&gt;

&lt;p&gt;And then there's the REST vs gRPC question. REST is convenient. gRPC is intentional. Protobuf-net.Grpc performance benefits, bidirectional streaming patterns, Envoy proxy integration, service mesh resilience — seniors choose the right protocol for the problem, not the one they're most comfortable with.&lt;br&gt;
The Security and Testing Gap Nobody Talks About&lt;br&gt;
Two areas that consistently separate true seniors from experienced mid-levels: security and testing maturity.&lt;/p&gt;

&lt;p&gt;Security in 2026 is protocol-level and supply-chain aware. OAuth 2.1 with PKCE, DPoP, JAR, PAR — these aren't buzzwords. They're requirements for SPA + microservice hybrid architectures. Policy-based authorization internals, claims transformation, dynamic policies — not just slapping &lt;code&gt;[Authorize]&lt;/code&gt; on a controller and calling it done.&lt;br&gt;
Supply chain security has become non-negotiable: SBOM generation, &lt;code&gt;dotnet list package --vulnerable&lt;/code&gt;, dependency lifecycle governance. If you don't know what's in your dependency tree, you don't control your attack surface.&lt;/p&gt;

&lt;p&gt;Testing maturity reflects architectural maturity. Contract testing with Pact, property-based testing with FsCheck, chaos and resilience testing with fault injection — these go far beyond "green tests." And observability as a test strategy — OpenTelemetry instrumentation, trace correlation across gRPC calls, debugging distributed latency chains — that's not DevOps. That's architecture validation.&lt;/p&gt;

&lt;h2&gt;
  
  
  What You Can Do Tomorrow
&lt;/h2&gt;

&lt;p&gt;If you're hiring or evaluating senior .NET developers, three concrete steps help.&lt;br&gt;
&lt;strong&gt;First: **Ask about runtime behavior, not just code quality. "What happens during a Gen 2 collection?" tells you more than any LeetCode problem.&lt;br&gt;
**Second:&lt;/strong&gt; Present a distributed systems failure scenario. How does the candidate reason about message delivery, idempotency, and consistency boundaries? This reveals system thinking — or the lack of it.&lt;br&gt;
&lt;strong&gt;Third:&lt;/strong&gt; Look at the testing approach. Does the candidate write tests that prove the system works, or tests that prove the system survives failure? That distinction is everything.&lt;/p&gt;




&lt;p&gt;After 17 years in the software industry, most of them spent in production-critical environments where downtime means real money, I've learned that the title "Senior Developer" means very little. What matters is the depth beneath the title.&lt;/p&gt;

&lt;p&gt;In 2026, being a senior .NET developer isn't about knowing more syntax. It's about understanding the runtime, the network, the database, and the failure modes in between. Mid-level developers write clean code. Seniors design resilient systems. Mid-level developers use async. Seniors understand async internals. Mid-level developers deploy microservices. Seniors understand distributed failure modes.&lt;/p&gt;

&lt;p&gt;The difference isn't code quality — it's system thinking.&lt;br&gt;
The developers who invest in understanding what happens beneath the abstractions — the CLR, the GC, the network, the message broker — are the ones who build systems that survive contact with reality.&lt;br&gt;
And in my experience, those developers are painfully rare. Which is exactly why knowing what to look for matters.&lt;/p&gt;

</description>
      <category>dotnet</category>
      <category>csharp</category>
      <category>career</category>
      <category>architecture</category>
    </item>
  </channel>
</rss>
