Browse Source

revise article

pull/24021/head
Alper Ebiçoğlu 4 months ago
parent
commit
d66598aa5d
  1. 0
      docs/en/Community-Articles/2025-10-17-Optimize-Your-App-For-Production/1.png
  2. 0
      docs/en/Community-Articles/2025-10-17-Optimize-Your-App-For-Production/10.png
  3. 0
      docs/en/Community-Articles/2025-10-17-Optimize-Your-App-For-Production/11.png
  4. 0
      docs/en/Community-Articles/2025-10-17-Optimize-Your-App-For-Production/11_1.png
  5. 0
      docs/en/Community-Articles/2025-10-17-Optimize-Your-App-For-Production/2.png
  6. 0
      docs/en/Community-Articles/2025-10-17-Optimize-Your-App-For-Production/3.png
  7. 0
      docs/en/Community-Articles/2025-10-17-Optimize-Your-App-For-Production/4.png
  8. 0
      docs/en/Community-Articles/2025-10-17-Optimize-Your-App-For-Production/5.png
  9. BIN
      docs/en/Community-Articles/2025-10-17-Optimize-Your-App-For-Production/6.png
  10. 0
      docs/en/Community-Articles/2025-10-17-Optimize-Your-App-For-Production/7.png
  11. 0
      docs/en/Community-Articles/2025-10-17-Optimize-Your-App-For-Production/8.png
  12. 0
      docs/en/Community-Articles/2025-10-17-Optimize-Your-App-For-Production/9.png
  13. 16
      docs/en/Community-Articles/2025-10-17-Optimize-Your-App-For-Production/Post.md
  14. 30
      docs/en/Community-Articles/2025-10-17-Optimize-Your-App-For-Production/Post2.md
  15. BIN
      docs/en/Community-Articles/2025-10-17-Optimize-Your-App-For-Production/image-20251020173353352.jpg
  16. BIN
      docs/en/Community-Articles/2025-10-17-Optimize-Your-App-For-Production/image-20251020181303926.png

0
docs/en/Community-Articles/2025-10-17-Optimize-Your-App-For-Production/image-20251019160137674.png → docs/en/Community-Articles/2025-10-17-Optimize-Your-App-For-Production/1.png

Before

Width:  |  Height:  |  Size: 352 KiB

After

Width:  |  Height:  |  Size: 352 KiB

0
docs/en/Community-Articles/2025-10-17-Optimize-Your-App-For-Production/image-20251020174712659.png → docs/en/Community-Articles/2025-10-17-Optimize-Your-App-For-Production/10.png

Before

Width:  |  Height:  |  Size: 206 KiB

After

Width:  |  Height:  |  Size: 206 KiB

0
docs/en/Community-Articles/2025-10-17-Optimize-Your-App-For-Production/image-20251020180232079.png → docs/en/Community-Articles/2025-10-17-Optimize-Your-App-For-Production/11.png

Before

Width:  |  Height:  |  Size: 237 KiB

After

Width:  |  Height:  |  Size: 237 KiB

0
docs/en/Community-Articles/2025-10-17-Optimize-Your-App-For-Production/image-20251020175737615.png → docs/en/Community-Articles/2025-10-17-Optimize-Your-App-For-Production/11_1.png

Before

Width:  |  Height:  |  Size: 46 KiB

After

Width:  |  Height:  |  Size: 46 KiB

0
docs/en/Community-Articles/2025-10-17-Optimize-Your-App-For-Production/image-20251019160303146.png → docs/en/Community-Articles/2025-10-17-Optimize-Your-App-For-Production/2.png

Before

Width:  |  Height:  |  Size: 354 KiB

After

Width:  |  Height:  |  Size: 354 KiB

0
docs/en/Community-Articles/2025-10-17-Optimize-Your-App-For-Production/image-20251019160355415.png → docs/en/Community-Articles/2025-10-17-Optimize-Your-App-For-Production/3.png

Before

Width:  |  Height:  |  Size: 487 KiB

After

Width:  |  Height:  |  Size: 487 KiB

0
docs/en/Community-Articles/2025-10-17-Optimize-Your-App-For-Production/image-20251019160413738.png → docs/en/Community-Articles/2025-10-17-Optimize-Your-App-For-Production/4.png

Before

Width:  |  Height:  |  Size: 323 KiB

After

Width:  |  Height:  |  Size: 323 KiB

0
docs/en/Community-Articles/2025-10-17-Optimize-Your-App-For-Production/image-20251019160500983.png → docs/en/Community-Articles/2025-10-17-Optimize-Your-App-For-Production/5.png

Before

Width:  |  Height:  |  Size: 366 KiB

After

Width:  |  Height:  |  Size: 366 KiB

BIN
docs/en/Community-Articles/2025-10-17-Optimize-Your-App-For-Production/6.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 256 KiB

0
docs/en/Community-Articles/2025-10-17-Optimize-Your-App-For-Production/image-20251020174203295.png → docs/en/Community-Articles/2025-10-17-Optimize-Your-App-For-Production/7.png

Before

Width:  |  Height:  |  Size: 191 KiB

After

Width:  |  Height:  |  Size: 191 KiB

0
docs/en/Community-Articles/2025-10-17-Optimize-Your-App-For-Production/image-20251020174103427.png → docs/en/Community-Articles/2025-10-17-Optimize-Your-App-For-Production/8.png

Before

Width:  |  Height:  |  Size: 242 KiB

After

Width:  |  Height:  |  Size: 242 KiB

0
docs/en/Community-Articles/2025-10-17-Optimize-Your-App-For-Production/image-20251020174425706.png → docs/en/Community-Articles/2025-10-17-Optimize-Your-App-For-Production/9.png

Before

Width:  |  Height:  |  Size: 190 KiB

After

Width:  |  Height:  |  Size: 190 KiB

16
docs/en/Community-Articles/2025-10-17-Optimize-Your-App-For-Production/Post.md

@ -20,7 +20,7 @@ I see way too many .NET apps go to prod like it’s still “F5 on my laptop.”
## 1) Publish Command and CSPROJ Settings
![image-20251019160137674](D:\github\volosoft\abp\docs\en\Community-Articles\2025-10-17-Optimize-Your-App-For-Production\image-20251019160137674.png)
![Publish Command and CSPROJ Setting](1.png)
Never go to production with debug build! See the below command which publishes properly a .NET app for production.
@ -51,7 +51,7 @@ dotnet publish -c Release -o out -p:PublishTrimmed=true -p:PublishSingleFile=tru
## 2) Kestrel Hosting
![image-20251019160303146](D:\github\volosoft\abp\docs\en\Community-Articles\2025-10-17-Optimize-Your-App-For-Production\image-20251019160303146.png)
![Kestrel Hosting](2.png)
By default, ASP.NET Core app listen only `localhost`, it means it accepts requests only from inside the machine. When you deploy to Docker or Kubernetes, the container’s internal network needs to expose the app to the outside world. To do this you can set it via environment variable as below:
@ -103,7 +103,7 @@ app.Run();
![image-20251019160355415](D:\github\volosoft\abp\docs\en\Community-Articles\2025-10-17-Optimize-Your-App-For-Production\image-20251019160355415.png)
![Garbage Collection and ThreadPool](3.png)
### GC Memory Cleanup Mode
@ -140,7 +140,7 @@ ThreadPool.SetMinThreads(200, 200);
## 4) HTTP Performance
![image-20251019160413738](D:\github\volosoft\abp\docs\en\Community-Articles\2025-10-17-Optimize-Your-App-For-Production\image-20251019160413738.png)
![HTTP Performance](4.png)
### HTTP Response Compression
@ -194,9 +194,9 @@ var json = JsonSerializer.Serialize(dto, MyJsonContext.Default.MyDto)
------
## 5) Data Layer (Probably Where Most Apps Slow Down)
## 5) Data Layer (Mostly Where Most Apps Slow Down!)
![image-20251019160500983](D:\github\volosoft\abp\docs\en\Community-Articles\2025-10-17-Optimize-Your-App-For-Production\image-20251019160500983.png)
![Data Layer](5.png)
### Reuse `DbContext` via Factory (Pooling)
@ -251,7 +251,7 @@ Use EF Core logging, SQL Server Profiler, or `EXPLAIN` (Postgres/MySQL) to find
### Migrations
In production run migrations manually, never do it on app startup.That way you can review schema changes, back up data and avoid breaking the live DB.
In production run migrations manually, never do it on app startup. That way you can review schema changes, back up data and avoid breaking the live DB.
@ -261,5 +261,5 @@ In production run migrations manually, never do it on app startup.That way you c
Use [Polly](https://www.pollydocs.org/) for retries, timeouts and circuit breakers for your DB or HTTP calls. Handles short outages gracefully
To keep the article short and for the better readability I splitted it into 2 parts -> [Continue with the second part here](Post2.md)...
To keep the article short and **for the better readability I spitted it into 2 parts 👉 [Continue with the second part here](Post2.md)...

30
docs/en/Community-Articles/2025-10-17-Optimize-Your-App-For-Production/Post2.md

@ -1,6 +1,6 @@
## 6) Telemetry (Logs, Metrics, Traces)
![image-20251020173353352](D:\github\volosoft\abp\docs\en\Community-Articles\2025-10-17-Optimize-Your-App-For-Production\image-20251020173353352.jpg)
![Telemetry](6.png)
The below code adds `OpenTelemetry` to collect app logs, metrics, and traces in .NET.
@ -31,9 +31,9 @@ When your app is on-air, you should know about the below tools. You know in airp
------
## 7) Build and Run Your .NET App in Docker the Right Way
## 7) Build & Run .NET App in Docker the Right Way
![image-20251020174203295](D:\github\volosoft\abp\docs\en\Community-Articles\2025-10-17-Optimize-Your-App-For-Production\image-20251020174203295.png)
![Docker](7.png)
A multi-stage build is a Docker technique where you use one image for building your app and another smaller image for running it. Why we do multi-stage build, because the .NET SDK image is big but has all the build tools. The .NET Runtime image is small and optimized for production. You copy only the published output from the build stage into the runtime stage.
@ -98,9 +98,9 @@ I'll explain what these Docker file commands;
## 8) Security
![image-20251020174103427](D:\github\volosoft\abp\docs\en\Community-Articles\2025-10-17-Optimize-Your-App-For-Production\image-20251020174103427.png)
![Security](8.png)
### 8.1) HTTPS Everywhere Even Behind Proxy
### HTTPS Everywhere Even Behind Proxy
Even if your app runs behind a reverse proxy like Nginx, Cloudflare or a load balancer, always enforce HTTPS. Why? Because internal traffic can still be captured if you don't use SSL and also cookies, HSTS, browser APIs require HTTPS. In .NET, you can easily enforce HTTPS like this:
@ -110,7 +110,7 @@ app.UseHttpsRedirection();
### 8.2) Use HSTS in Production
### Use HSTS in Production
HSTS (HTTP Strict Transport Security) tells browsers:
@ -127,7 +127,7 @@ if (!app.Environment.IsDevelopment())
When you use HSTS, it sends browser this HTTP header: ` Strict-Transport-Security: max-age=31536000; includeSubDomains`. Browser will remember this setting for 1 year (31,536,000 seconds) that this site must only use HTTPS. And `includeSubDomains` option applies the rule to all subdomains as well (eg: `api.abp.io`, `cdn.abp.io`, `account.abp.io` etc..)
### 8.3) Store Secrets on Environment Variables or Secret Stores
### Store Secrets on Environment Variables or Secret Stores
Never store passwords, connection strings, or API keys in your code or Git. Then where should we keep them?
@ -147,7 +147,7 @@ Or **Secret stores** like: Azure Key Vault, AWS Secrets Manager, HashiCorp Vault
### 8.4) Add Rate-Limiting to Public Endpoints
### Add Rate-Limiting to Public Endpoints
Don't forget there'll be not naive guys who will use your app! We've many times faced this issue in the past on our public front-facing websites. So protect your public APIs from abuse, bots, and DDoS. Use rate-limiting!!! Stop brute-force attacks, prevent your resources from exhaustion...
@ -167,7 +167,7 @@ app.UseRateLimiter();
- Also there's an open-source rate-limiting library -> [github.com/stefanprodan/AspNetCoreRateLimit](https://github.com/stefanprodan/AspNetCoreRateLimit)
- Another one -> [nuget.org/packages/Polly.RateLimiting](https://www.nuget.org/packages/Polly.RateLimiting)
### 8.5) Secure Cookies
### Secure Cookies
Cookies are often good targets for attacks. You must secure them properly otherwise you can face cookie stealing or CSRF attack.
@ -187,9 +187,9 @@ options.Cookie.SameSite = SameSiteMode.Strict; // or Lax
## 9) Startup/Cold Start
![image-20251020174425706](D:\github\volosoft\abp\docs\en\Community-Articles\2025-10-17-Optimize-Your-App-For-Production\image-20251020174425706.png)
![Cold Start / Startup](9.png)
### 9.1) Keep Tiered JIT On
### Keep Tiered JIT On
The **JIT (Just-In-Time) compiler** converts your app’s Intermediate Language (IL) into native CPU instructions when the code runs. _Tiered JIT_ means the runtime uses 2 stages of compilation. Actually this setting is enabled by default in modern .NET. So just keep it on.
@ -201,7 +201,7 @@ The **JIT (Just-In-Time) compiler** converts your app’s Intermediate Language
### 9.2) **Use PGO (Profile-Guided Optimization)**
### Use PGO (Profile-Guided Optimization)
PGO lets .NET learn from real usage of your app. It profiles which functions are used most often, then re-optimizes the build for that pattern. You can think of it as the runtime saying:
@ -215,7 +215,7 @@ In .NET 8+, you don’t have to manually enable PGO (Profile-Guided Optimization
## 10) Graceful Shutdown
![image-20251020174712659](D:\github\volosoft\abp\docs\en\Community-Articles\2025-10-17-Optimize-Your-App-For-Production\image-20251020174712659.png)
![Shutdown](10.png)
When we break up with our lover, we often argue and regret it later. When an application breaks up with an operating system, it should be done well 😘 ...
When your app stops, maybe you deploy a new version or Kubernetes restarts a pod... the OS sends a signal called `SIGTERM` (terminate).
@ -237,7 +237,7 @@ On K8s, set `terminationGracePeriodSeconds` and wire **readiness**/startup probe
## 11) Load Test
![image-20251020180232079](D:\github\volosoft\abp\docs\en\Community-Articles\2025-10-17-Optimize-Your-App-For-Production\image-20251020180232079.png)
![Load Test](11.png)
Sometimes arguing with our lover is good. We can see her/his face before marrying 😀 Use **k6** or **bombardier** and test with realistic payloads and prod-like limits. Don't be surprise later when your app is running on prod! These topics should be tested: `CPU %` , `Time in GC` , `LOH Allocations` , `ThreadPool Queue Length` and `Socket Exhaustion`.
@ -255,4 +255,4 @@ Sometimes arguing with our lover is good. We can see her/his face before marryin
- 7K stars on GitHub
- GitHub address: https://github.com/codesenberg/bombardier
[![image-20251020175737615](D:\github\volosoft\abp\docs\en\Community-Articles\2025-10-17-Optimize-Your-App-For-Production\image-20251020175737615.png)](https://trends.google.com/trends/explore?cat=31&q=bombardier%20%2B%20benchmarking,k6%20%2B%20benchmarking)
[![Bombardier vs K6](11_1.png)](https://trends.google.com/trends/explore?cat=31&q=bombardier%20%2B%20benchmarking,k6%20%2B%20benchmarking)

BIN
docs/en/Community-Articles/2025-10-17-Optimize-Your-App-For-Production/image-20251020173353352.jpg

Binary file not shown.

Before

Width:  |  Height:  |  Size: 64 KiB

BIN
docs/en/Community-Articles/2025-10-17-Optimize-Your-App-For-Production/image-20251020181303926.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 276 KiB

Loading…
Cancel
Save