Skip to content

App Service Linux Does NOT Properly Handle Application Lifecycle #258

@corcorpj

Description

@corcorpj

The Problem

Azure App Service for Linux does not properly integrate with .NET application lifecycle hooks when stopping or restarting applications. Specifically:

az webapp stop does NOT:

  • Send SIGTERM to the running container
  • Trigger IHostApplicationLifetime.ApplicationStopping
  • Call BackgroundService.StopAsync() methods
  • Allow any graceful shutdown whatsoever

The application process is simply killed at the infrastructure level without any notification to the application code.

Why This Matters

Modern .NET applications use built-in lifecycle hooks for critical cleanup operations:

  • Completing in-flight work
  • Releasing database connections
  • Flushing logs and telemetry
  • Releasing distributed locks
  • Gracefully stopping background services
  • Preventing data corruption

These are not "nice-to-have" features - they are core patterns in ASP.NET Core that Microsoft itself promotes and documents extensively.

The Disconnect

Microsoft provides:

  • Comprehensive documentation on graceful shutdown in .NET
  • IHostApplicationLifetime APIs specifically for shutdown hooks
  • BackgroundService base class with StopAsync() methods
  • App Service as a managed hosting platform for .NET

But Azure App Service doesn't actually honor these lifecycle contracts when you stop or restart the service.

Current "Solutions" Are Inadequate

Deployment Slots: Not viable when your application cannot have multiple instances running simultaneously (exclusive locks, singleton processing, queue consumers, etc.)

Manual Workarounds: Developers are forced to:

  • Call Kudu APIs to manually kill processes
  • Implement custom shutdown endpoints
  • Add complex orchestration logic to GitHub Actions
  • Hope that deployment triggers proper shutdown (it often doesn't)

This is unacceptable for a Microsoft hosting platform running Microsoft frameworks.

Impact on Developer Experience

This creates:

  • Frustration and wasted time troubleshooting why "standard" .NET patterns don't work
  • Loss of confidence in Azure as a reliable platform
  • Production issues from incomplete shutdown (data loss, corruption, orphaned resources)
  • Complexity - developers forced to implement workarounds for basic functionality that should "just work"
  • Bad impressions of Azure compared to competitors where lifecycle management works correctly

What Should Happen

When a developer runs az webapp stop or az webapp restart:

  1. Azure should send SIGTERM to the container (standard Docker practice)
  2. The .NET runtime should receive this and trigger ApplicationStopping
  3. Background services should have their StopAsync() methods called
  4. The application should have time (configurable via WEBSITES_CONTAINER_STOP_TIME_LIMIT) to complete shutdown
  5. Only then should the process be forcefully killed if needed

This is how Docker containers work. This is how Kubernetes works. This is how every other container platform works. Azure App Service should work this way too.

The Ask

Microsoft needs to:

  1. Fix the integration between App Service infrastructure commands and container lifecycle
  2. Document the current behavior honestly - don't pretend graceful shutdown works when it doesn't
  3. Provide a supported solution for single-instance applications that need graceful shutdown
  4. Test these scenarios - clearly this workflow was never properly tested with real .NET applications

Conclusion

It is utterly ridiculous that deploying a .NET application to Microsoft's own managed hosting platform requires custom workarounds to achieve basic lifecycle management that works correctly on every other container platform.

This is not about "fancy bumpless parallelism" or zero-downtime deployments. This is about basic application lifecycle management - starting and stopping an application cleanly. Microsoft promotes these patterns in .NET, documents them extensively, and then their own hosting platform doesn't support them.

This severely impacts impressions of Azure's usability and maturity as a platform. When developers can't rely on fundamental contracts between the framework and the hosting environment, trust in the entire ecosystem is damaged.


TL;DR: az webapp stop should trigger graceful shutdown in .NET applications. It doesn't. This is a critical gap that forces developers into hacky workarounds for basic functionality that should work out of the box on a Microsoft platform hosting Microsoft frameworks.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions