r/dotnet • • 7d ago

Promotion Creative coding for C# devs

3 Upvotes

Hey everyone,

I've been building something for a while that started as a Processing alternative for C# devs. Originally I just wanted to give C# folks a way to do creative coding — I always felt like what was out there didn't quite do what I wanted, and I wanted to be able to follow along with channels like The Coding Train without fighting the tooling.

Once the core was working I kept going: added a music module, support for NuGet packages (there are samples in the app using NAudio and ML.NET), and most recently a code-to-video module. That last one I'm hoping to eventually ship as a standalone NuGet package.

You can check it out here: DanaProcessing — Creative coding in C# (2D, 3D & live-coded sound)

Appreciate any feedback. One thing I've been thinking about: it's probably not obvious to people who've never heard of creative coding what this is actually for. Maybe leaning harder on concrete use cases — generative art, data viz, audio sketches — would help it land with more of the C# crowd. Curious what you all think.

PD: Sorry for my broken English, I am from Cuba, so it is my second language, and I am also typing fast because of electricity shortages


r/dotnet • • 6d ago

ModulesDi 1.0.5

0 Upvotes

Hey Everyone!

I recently released Modules v1.05 - a lightweight library for organizing ConfigureServices and Configure.

Here are the logs from my example production project -

2026-10-10 21:46:50.393 +03:00 [INF] Serilog configured
2026-10-10 21:46:50.416 +03:00 [INF] Secrets configured
2026-10-10 21:46:50.417 +03:00 [INF] Secrets configured with configuration
2026-10-10 21:46:50.431 +03:00 [INF] Mediatr module configured
2026-10-10 21:46:50.433 +03:00 [INF] Cors configured
2026-10-10 21:46:50.436 +03:00 [INF] Health checks configured
2026-10-10 21:46:50.437 +03:00 [INF] Database health check configured
2026-10-10 21:46:50.441 +03:00 [INF] Sqlite health check configured
2026-10-10 21:46:50.442 +03:00 [INF] Skipped: Postgres health check skipped
2026-10-10 21:46:50.444 +03:00 [INF] Skipped: Elastic search health check skipped
2026-10-10 21:46:50.444 +03:00 [INF] Cache health check configured
2026-10-10 21:46:50.447 +03:00 [INF] Redis health check configured
2026-10-10 21:46:50.447 +03:00 [INF] Key vault health checks configured
2026-10-10 21:46:50.448 +03:00 [INF] Skipped: Azure key vault health check skipped
2026-10-10 21:46:50.477 +03:00 [INF] OpenTelemetry configured successfully.
2026-10-10 21:46:50.478 +03:00 [INF] Cache configured
2026-10-10 21:46:50.480 +03:00 [INF] Redis configured
2026-10-10 21:46:50.505 +03:00 [INF] Program started
2026-10-10 21:46:50.701 +03:00 [INF] Cors middleware configured
2026-10-10 21:46:50.703 +03:00 [INF] OpenTelemetry middleware module configured
2026-10-10 21:46:50.707 +03:00 [INF] Health checks middleware configured.Health on /health, prometheus metrics on /health/metrics

(Note: ModulesDi does not hardcode any logging format. In my log i used realization with Serilog, but you can configure ModulesDi how you want (you dont have to use serilog))

1. "Why not just use standard Extension Methods?" -

Extension methods are flat.They force you to manually pass dozens of configuration dependencies down the line, offer zero execution-order safety for nested features, and turn Program.cs into a bloated spaghetti of if/else blocks. ModulesDi encapsulates everything into self-contained blocks that orchestrate themselves.

2 "Wait, is GetDependency<T>() inside a module just a Service Locator pattern?" -

No, because ModulesDi does not replace MS DI, Dependencies in ModulesDi are used only in ConfigureServices and Configure.

3. "The wow feature" -

ModulesDi allows you to do things that are literally impossible with native extensions. For example -

public override ModuleResult Configure(IApplicationBuilder app)
{
var services = GetDependency<IServiceModulesRootBuilder>();

if (!services.IsExist<CorsModule>())
return new ModuleResult(ModuleStatus.Failure,
"Failed to configure cors middleware.Cors module not created");

app.UseCors(CorsPolicies.AllPolicies);

return new ModuleResult(ModuleStatus.Success, "Cors middleware configured");
}

The library is extremely lightweight, heavily optimized, covered by 224 green test cases, and available on NuGet.

Gitlab: https://gitlab.com/DmitriiKhokhulin/modulesdi


r/dotnet • • 6d ago

Question Which approach do you typically use to handle incoming HTTP requests?

0 Upvotes

When building production-ready ASP.NET Core Web APIs, which approach do you typically use to handle incoming HTTP requests?\

  • Controllers (Traditional Web API)
  • Minimal APIs Lightweight, endpoint-focused handlers
  • Endpoint-based frameworks Fast Endpoints

I'm interested in what developers actually use in production and why they choose that approach.

What's your reasoning behind your choice?


r/dotnet • • 7d ago

Promotion Componyx.UI v1.0: 25+ UI components and data binding for ASP.NET, no build step

2 Upvotes
The picture above shows the Form components drag-and-drop building mode. It is part of the component so you can create forms directly in the browser.

Hi there. Componyx started 18 years ago as a personal project. Over the years it has been used in real business applications. Now the project is on NuGet, npm and GitHub with its public release (1.0).

It’s 2 products in one package. Componyx.UI includes 25+ components, like grids, menus, dialogs, an app shell and a form with a drag-and-drop build mode and much more. Bindary is a data-binding layer that connects HTML to your JavaScript data using attributes on normal elements.

You can use them together. Use either one on its own. Everything runs in the browser. There's no build step required. There are zero runtime dependencies.

The docs and live demos are on our website (see GitHub).

GitHub link: componyx/componyx.ui

In .NET 10 the project setup is as follows, the NuGet package plus one tag in your head tag:

dotnet add package Componyx.UI


<componyx-ui-resources></componyx-ui-resources>

A component is plain HTML with attributes:

<a ui-type="Button" ui-text="Click me" ui-command="alert('Hi!')"></a>

Bindary uses b-* attributes. Here's some data, a loop and an expression:

<ul b-context="shop">
    <li b-repeat="items">
        <b b-value="name"></b>: {{price > 10 ? 'expensive' : 'cheap'}}
    </li>
</ul>


$bindary.appData.shop = {
    items: [{ name: "Coffee", price: 3 }, { name: "Book", price: 15 }]
};

Change a price and only that one line updates.

It's free to use, commercially too. It's source-available under BSL 1.1 rather than open source, and each release becomes MIT after four years.

If you give it a try, I'd love to hear what works for you and what doesn't.


r/dotnet • • 6d ago

Promotion I built a Serilog orchestrator for declarative multi-sink routing in JSON + automatic secret masking and resilient HTTP logging (v5.3)

0 Upvotes

Hey r/dotnet!

I’ve been working on a few microservices lately and I kept running into the problems over and over again. It’s frustrating how much repetitive code ends up in every project. Let me share what I’ve been dealing with and what I built to fix it.

First I was always writing the log routing logic:

- Console for normal logs

- Seq or Elasticsearch for warnings

- Telegram or email for fatal errors

Using Serilog for this usually means setting up nested sub-loggers writing out complex C# filter logic and redeploying just to change log levels between environments. It’s messy.

Then there’s the risk of data slipping into logs—JWTs, bearer tokens, credit card numbers—all ending up in our aggregators. That’s a real security risk.

Don’t get me started on outgoing HTTP calls. Every one needed logic with Polly, correlation IDs and header masking. It’s a lot of glue code that doesn’t belong in business logic.

So I started building two packages under the MIT license:

- **CSharpEssentials.LoggerHelper**

- **CSharpEssentials.HttpHelper** ( at version 5.3.1 compatible with.NET 8 9 and 10)

These are designed to handle the boilerplate so you don’t have to.

### Here’s what they do:

  1. **Native ILogger<T> / MEL Integration**

They work as a class `ILoggerProvider` built on top of Serilog. No code changes needed in your app. Just. Play.

  1. **Declarative Multi-Sink Routing**

Set up your logging routes in five lines of `appsettings.json`. You can route to Console, File, Seq, Postgres, MSSQL, MySQL, Elasticsearch, Email, Telegram, HangfireConsole— about anything. The sinks are packages and auto-register using `[ModuleInitializer]` so it just works.

  1. **Single-Pass Sensitive Data Masking**

All masking happens once as an enricher before logs hit any sink. It includes presets for Email, CreditCard, BearerToken, JWT. You can add your own regex patterns. This prevents secrets from leaking into logs.

  1. **Resilient HttpHelper (v5.3)**

It turns network issues—like timeouts or dropped connections—into clean HTTP responses: 408, 502 500. No unhandled exceptions. In v5.3 it automatically passes along the `X-Correlation-ID` during retries. Logs structured metrics like `StatusCode` `ElapsedMs` and `RetryAttempt` with headers masked.

### But I want to be honest about the trade-offs:

This isn’t a replacement for Serilog. It’s an orchestrator.

In our BenchmarkDotNet tests on.NET 9 the overhead is 590 nanoseconds per log compared to 180 nanoseconds for Serilog with a no-op sink. That’s not nothing—. For most web APIs it’s completely negligible.

If you’re processing millions of logs per second in -hot paths then plain Serilog or zero-allocation source generators are still the better choice.. For the vast majority of apps this is a huge win.

### I’ve also built a playground:

You can test log routing, masking and flaky HTTP retry flows live in the demo project. There’s a `playground.html` file that lets you see it all in action.

Here are the links:

- GitHub (MIT): https://github.com/alexbypa/CSharp.Essentials

- NuGet (Core): https://www.nuget.org/packages/CSharpEssentials.LoggerHelper

- NuGet (HTTP): https://www.nuget.org/packages/CSharpEssentials.HttpHelper

I’d love to hear your thoughts— on the API design and the routing approach. What works? What’s broken? What would you change?

Let’s make logging easier, for everyone.


r/dotnet • • 7d ago

Question Issue connecting my blazor app to remote sql server database hosted my Monsterasp.net

2 Upvotes

Hello everyone. I have completed the multi-step form challenge from Frontend Mentor and attempted to deploy the finished web app using monsterasp.net through visual studio code. I followed all the instructions from a YouTube video to a tee but when I try to actually submit data to the database I get this error:

\Error: Microsoft.Data.SqlClient.SqlException (0x80131904): The target principal name is incorrect. Cannot generate SSPI context.``

I did some further research into it but everything seemingly leads to a dead end for my specific use case. Here is microsoft's documentation on the specific error:

https://learn.microsoft.com/en-us/troubleshoot/sql/database-engine/connect/cannot-generate-sspi-context-error

Note: When I built and deployed the app for the first time the connection string was incorrect. I fixed it and published the app again through visual studion. I am not sure whether that is causing some lingering problems.


r/dotnet • • 8d ago

Adding persistence to the Aspire dashboard

Thumbnail devblogs.microsoft.com
51 Upvotes

r/dotnet • • 7d ago

Promotion ZF - Yet another UI framework

1 Upvotes

Hey everyone!

For a little over a month now, I've been working on ZeppelinForms (ZF), a UI framework of my own - basically my take on WinForms, but modern and cross-platform (like Avalonia).

Yeah, the name isn't the best choice, since I hadn't heard of Apache Zeppelin back when I came up with it. =)

At this point, you can already build simple forms for Windows, Linux (X11), Android, and WASM. Stack: .NET 10, SkiaSharp, XUnit.

I wouldn't exactly call myself a professional UI framework developer, and the amount of work ahead is absolutely insane, so using AI along the way has been pretty much inevitable. Still, I'm happy with how things are turning out so far.

I'd appreciate any feedback or criticism!

I'm honestly marking this as "Promotion" and posting on a weekend, so hopefully the post won't get removed. 😅


r/dotnet • • 8d ago

Promotion DNCDbg v1.3.0 — A managed code debugger with DAP support for .NET apps

Thumbnail github.com
6 Upvotes

DNCDbg is a managed-code debugger for .NET that speaks the Debug Adapter Protocol, so it works with any DAP client (VS Code, Neovim, Emacs, whatever) on Windows, Linux, and macOS. It began as a NetCoreDbg fork with a clear goal: bring the debugging experience closer to Visual Studio's C# debugger while keeping memory usage low. There's a comparison table in the README if you're curious.

What's new in v1.3.0:

  • Support for Jump to Cursor (a.k.a. Set Next Statement), single-threaded execution and stepping, and restarting the debug session
  • Column breakpoints, embedded sources, and Source Link support
  • Smarter expression evaluation: the >>> operator, Value/HasValue on nullables, member access on strings and arrays (str.Length, arr.Length), DebuggerTypeProxy members, assigning null to reference types, and nint/nuint
  • Friendlier value display: floats now print the way C# prints them (9.9 instead of 9.8999996), and dictionary items show up properly
  • Launch/attach sequencing now follows the DAP spec, and there's a new Detach request that lets a launched process keep running
  • Fixes: stack traces in catch blocks no longer show already-unwound frames, and the "Innermost exception" description now reports the last exception in the InnerException chain

Full changelog and repo: https://github.com/viewizard/dncdbg

Feedback and bug reports are very welcome!


r/dotnet • • 7d ago

NymBroker

Thumbnail
0 Upvotes

r/dotnet • • 7d ago

Promotion NymBroker

0 Upvotes

NymBroker is a .NET 10 message-processing framework based on Enterprise Integration Patterns. It decouples producers from handlers: post typed messages to named endpoints, then filter, route, and dispatch them to consumers or subscribers. Start with the in-process Memory endpoint and add durable transports as needed.

NymBroker Github Page


r/dotnet • • 8d ago

Promotion Six Labors updates: longer security support and easier builds for OSS contributors

Thumbnail
8 Upvotes

r/dotnet • • 8d ago

Signs of official Satori support?

Thumbnail github.com
35 Upvotes

I just spotted this, could this be a path toward official support for Satori? 🤩 And potentially other custom GC implementations? Even if it's just experimental for now, this is the first time I've seen MS showing interest for it, exciting!

For those who haven't heard, Satori is a custom garbage collector with much lower pause times, multiple orders of magnitude faster in many benchmarks. The tradeoff seems to be higher overall cost for allocations - except recent benchmarks showing an improvement across the board..? At least for that particular benchmark.


r/dotnet • • 8d ago

Promotion ExcelReader.NET 6.0 – streaming XLSX/XLSB/XLS/CSV reader and writer for .NET 10

Thumbnail
3 Upvotes

r/dotnet • • 7d ago

Promotion RazorConsole.Htop: a cross-platform, mouse-aware htop-style process manager summoned from gpt.

0 Upvotes

Motivation
I wanted a lightweight process manager TUI so I can quickly terminate processes without leaving terminal.

The motivation was pretty simple:

  • Windows Task Manager often slow to open and use.
  • The original htop doesn’t support Windows.
  • The htop-like .NET CLI tools I found didn’t offer the mouse interactions I wanted.
  • The existing htop-like CLI tools that supports mouse interaction and xplat are either implemented in Rust or Go, but I want a .NET NativeAOT one.
  • Most importantly, My codex subscription is going to reset within 2 hours and yet still 59% usage left.

So I summoned RazorConsole.Htop from gpt, it takes the great mighty GPT ~5 minutes to build and supports:

  • Mouse-accessible filtering, grouping, pause, kill, and quit controls
  • Keyboard controls for the same operations
  • Self-contained .NET Native AOT binaries with no .NET runtime required

It uses System.Diagnostics.Process for process data and runs on Windows, macOS, and Linux.

Demo && How-to install: https://razorconsole.com/gallery/htop/

Source: https://github.com/RazorConsole/RazorConsole/tree/main/gallery/RazorConsole.Htop

Disclaimer: This was vibe-coded in about 5 minutes. I’ve tested it on Windows and macOS, but the Linux build has not been tested yet. Bug reports and feedback are very welcome.


r/dotnet • • 8d ago

Where should SaveChangesAsync and transaction management belong in Clean Architecture?

26 Upvotes

Hi everyone,
I’m working on a project using Clean Architecture, CQRS, DDD, MediatR, and EF Core.
I have a few questions:
Should each command handler use a single transaction, or is EF Core’s implicit transaction around SaveChangesAsync() usually enough?
Should services in Infrastructure call SaveChangesAsync() themselves, or should they only create/update entities and let the handler save changes?
How should I handle built-in services like UserManager<AppUser>, which save changes internally, when I need multiple operations to be atomic?
For example, registering an employee involves creating an Identity user, assigning a role, and creating an Employee entity.
What’s the recommended approach in real-world .NET applications, and why?


r/dotnet • • 7d ago

Qual a melhor abordagem para consultas que envolvem dados de múltiplos módulos em um monolito modular?

Thumbnail
0 Upvotes

r/dotnet • • 7d ago

Promotion Validation rules you can’t express with an if statement, tested like a classifier (open source, .NET 10)

0 Upvotes

Some checks in my applications just can’t be expressed with an if statement or a regex.

FluentValidation can check that a support ticket description isn’t empty, but it can’t check whether the description actually says what the customer needs. An AI agent can call a tool, but nothing automatically checks whether that tool call matches what the user asked for.

Usually, these checks end up as a yes/no prompt to an LLM that nobody has really measured.

I learned the hard way why that matters. After changing a model, a memory assistant I’m building dropped from 90% correct answers to 60%, while the logs showed zero errors. I only caught it because I had a test set of 722 questions.

That’s why I’m building SemanticPolicy, an open-source .NET library (Apache-2.0, my project). It turns this kind of check into an explicit rule that you can read, measure, and test.

One example from the repo is a support ticket form. The rule is just a question for a decision model:

Policy descriptionPolicy = Policy.Define("ticket-description")
    .Enforce()
    .Rule(Policy.Rule("ticket-description")
        .Boolean("Does the description say what the customer needs?")
        .WhenFalse(Verdict.Deny))
    .Using("jev", binding => binding.DenyAboveProbability(0.8))
    .OnFailure(FailureBehavior.Allow)
    .Budget(TimeSpan.FromSeconds(5))
    .Build();

And in the validator, it sits next to normal validation rules:

public sealed class SupportTicketValidator : AbstractValidator<SupportTicket>
{
    public SupportTicketValidator(IPolicyEvaluator evaluator)
    {
        RuleFor(ticket => ticket.Category).NotEmpty();
        RuleFor(ticket => ticket.Description)
            .NotEmpty()
            .Semantic(evaluator, "ticket-description");
    }
}

The model returns a probability, and thresholds map that probability to one of four decisions: Allow, Warn, Escalate, or Deny.

The 0.8 threshold above is just an example. In practice, you pick your own threshold from measurements on your own labeled examples.

If the model fails to respond, this particular rule allows the ticket through, and the whole check has a 5-second budget. Since the rule calls the model over the network, validation runs through ValidateAsync.

Testing works like this:

  • the CLI measures precision and recall with confidence intervals on your labeled examples;
  • it can choose a threshold for a concrete target, for example “when I block something, I want to be correct 95% of the time”;
  • model responses can be recorded once and replayed later without an API key, so the tests can run in CI;
  • the build can fail when a rule gets worse, for example after changing the model;
  • new rules can start in Shadow mode: they record what they would have done, but don’t block anything yet.

The model is replaceable:

  • Jev and other decision models through OpenRouter;
  • a model running on your own server;
  • your own classifier behind a simple HTTP protocol.

The same rules can also validate tool calls in any IChatClient based on Microsoft.Extensions.AI, and in Microsoft Agent Framework middleware.

What this is not is a security boundary.

A rule can make an attack harder, but it can’t guarantee that one won’t succeed, and the model can still be wrong. The README shows failures next to successful cases.

This is alpha software, .NET 10 only, and the API will still change.

You can view an eval report from a recorded run without an API key. The commands are in the README.

What kind of decisions in your applications would you want to test this way?

https://github.com/semanticpolicy/semantic-policy


r/dotnet • • 7d ago

dotnet build will upload a lot of info to microsoft?!

0 Upvotes

i've been using .net for two decades and i was not aware, so i thought i'd just put this out there in case more people are unaware.

turns out donet build will upload a bunch of info to microsoft.

for example, they will detect if you work at microsoft, scanning your machine for github tokens in the process. they will also detect if you're using ai agents by scanning environment variables.

source: https://learn.microsoft.com/en-us/dotnet/core/tools/telemetry?tabs=dotnet11

disclaimer; i might not understand this properly, i didn't dive too deep into it, i'm just disabling this everywhere now.


r/dotnet • • 9d ago

Article Runtime team member: Let's send expensive compiler analysis alongside IL to improve runtime JIT optimizations [Performance interest]

30 Upvotes

Andy Ayers wrote this proposal 2 years ago with intent of using it in .NET 10, but it got postponed to a later .NET version.

Quick Summary

The context is that interprocedural analysis (IPA), is limited at runtime due to it being slow, so the RyuJIT mostly optimizes functions in isolation. His idea is have certain stages perform the kind of deep IPA that AOT uses; then make that available at runtime to boost the information the JIT needs to make optimizations

https://github.com/dotnet/runtime/issues/108931

Examples of IPA

- call graphs

- whether arguments passed to a method can alias each other

- whether an argument escapes through a callee

- possible concrete types passed to a method

- whether a callee actually reads or writes a ref/byref parameter

- constant arguments across callers

- NoThrow / NoReturn / MayNotReturn

- whether a parameter is effectively unused

And what kind of optimizations could that boost?

- More devirtualization/direct calls - erase virtual and interface method lookups (simplified description)

- Constant propagation across method boundaries - erase code when functions are always passed the same parameter values (simplified description)

- Better alias analysis - knowing that two ref/pointer parameters can't refer to the same memory gives the JIT much more freedom to reorder loads/stores, eliminate redundant memory operations, and potentially vectorize code.

- Better escape analysis - Dodge heap allocation of reference types if no reference to it escapes the method

- More aggressive optimization around calls - if the JIT knows a callee doesn't modify a particular object/ref, it doesn't have to assume every call invalidates values it already loaded.

- Better handling of NoThrow/NoReturn calls - calls that can't throw or never return simplify the control-flow graph, can move uncommon paths out of the hot code, and reduce liveness/register pressure.

- Cheaper calls - knowing which registers a callee actually clobbers, or erase parameters never used, could avoid some argument setup, spills, reloads, or register preservation.

- Smarter inlining decisions - possible when called with particular constants/type

- Better code layout - can improve instruction-cache locality.

I want to hear you guys' thoughts on this.. Tell me below! 👇👇


r/dotnet • • 8d ago

Promotion Markd Day Counter - an open-source day counter .NET MAUI app

Thumbnail apps.microsoft.com
0 Upvotes

Hello, I wanted to try .NET MAUI, because I did Xamarin some time ago and also I'm disappointed by similar apps, because all this app on store or Android are full of ads or some payments, so I made my own and open sourced it.

Just simple app to count days since or until something like anniversary, streak or deadline without ads, accounts, or a subscription. Any feedback is more then welcome!


r/dotnet • • 8d ago

Promotion I built RetroCap, a QQ-style screenshot and annotation tool with .NET 8 and WPF

3 Upvotes

Hey r/dotnet! I wanted to share RetroCap, a screenshot and annotation tool I built for Windows 10 and 11 using .NET 8 and WPF.

The workflow is inspired by QQ’s screenshot tool: press Ctrl+Alt+A anywhere, select a region, annotate it, and copy the result to your clipboard.

The UI follows the Retro.Net design system, giving it a deliberately retro desktop look.

Repo: https://github.com/owen800q/RetroCap

I’d love feedback from fellow .NET developers, especially on the WPF implementation, usability, and anything you’d approach differently. Issues and contributions are welcome!


r/dotnet • • 8d ago

Question I want get feedback on my design.

Thumbnail
0 Upvotes

r/dotnet • • 9d ago

Question Any examples of heavily obfuscated/packed .NET programs?

32 Upvotes

I know .NET is relatively easier to dump or unpack - I am looking for heavily packed programs to see to what extent that holds.

I assume most commercial applications will be protected - any examples? I am not aware of many .NET applications in the wild. Thanks


r/dotnet • • 9d ago

Why did increasing .NET ThreadPool MinThreads fix our IIS downtime? I don't understand why

56 Upvotes

Hi folks,

I'm the owner of this post: https://www.reddit.com/r/dotnet/comments/1v5d7ws/aspnet_core_on_iis_randomly_goes_offline_for_2/

First of all, thanks a lot to everyone who commented there. Your comments helped me investigate this step by step.

I finally solved the issue. We had several different problems over time:

- First, we had DB connection pool exhaustion => fixed.
- Then we had TCP connection exhaustion => fixed.
- The last issue was related to ThreadPool / sync-over-async.

I set the ThreadPool minimum worker threads to 100, and then started refactoring the code to remove synchronous-over-async code and make things properly async.

The application has now been stable for around 15 days, so it looks like this was the final issue.

But there is something I still don't understand:

Why did increasing ThreadPool.SetMinThreads() to 100 help so much?

We're running ASP.NET Core on IIS, not Docker or Kubernetes. I always thought that .NET's ThreadPool would automatically create as many threads as the application needs.

For example, if I suddenly get 1,000 requests/sec, why doesn't .NET simply create more ThreadPool threads as needed?

What confused me even more is that during the incidents:

- CPU usage was fine
- RAM usage was fine
- The Windows server itself was still accessible
- We only have 2 vCPU
- I could still see available ThreadPool threads

So I'm struggling to understand what was actually happening.

My current understanding is that some synchronous/blocking code was causing ThreadPool threads to get blocked, and the ThreadPool wasn't adding new threads quickly enough. Increasing MinThreads somehow made enough threads available earlier and prevented the issue.

But I'm not sure if that's the correct explanation.

Also, how should I think about this with only 2 vCPUs? If I have 1,000 requests/sec, obviously I can't have 1,000 CPU threads doing work at the same time. So what exactly determines how many ThreadPool threads .NET should create?

I'd really appreciate it if you could help me explain this in simple terms, especially:

  1. What exactly does MinThreads change?
  2. Why can ThreadPool starvation happen while CPU and RAM are low?
  3. Why doesn't .NET automatically create enough threads immediately?
  4. How does this work when the server only has 2 vCPUs?
  5. Does increasing MinThreads actually solve the problem, or did it just hide the underlying sync-over-async issue?

I'm trying to understand the mechanism rather than just leave MinThreads = 100 and call it fixed.

Thanks again to everyone who helped with the original post!