Session state is a core mechanism in ASP.NET for maintaining user-specific data across multiple HTTP requests. By default, ASP.NET sessions expire after 20 minutes of inactivity, but most applications need to adjust this based on their specific requirements. This guide covers every method to configure session timeout, the different session state modes, sliding versus absolute expiration, and best practices for reliable session management.
Understanding ASP.NET Session State
When a user visits an ASP.NET application, the server creates a unique session identified by a Session ID (typically stored in a cookie named ASP.NET_SessionId). This session acts as a server-side dictionary where you can store objects that persist across requests for that specific user.
Session Lifecycle
- Creation: A new session is created on the first request (or when
Sessionis first accessed). - Active: The session remains active as long as the user sends requests within the timeout window.
- Sliding Expiration: By default, each request resets the timeout countdown.
- Expiration: If no request is received within the timeout period, the session is marked as expired and its data is eligible for cleanup.
- Abandonment: Code can explicitly end a session with
Session.Abandon().
Default Session Configuración
The default ASP.NET session configuration is:
- Timeout: 20 minutes
- Mode: InProc (in-process, stored in server memory)
- Cookieless: false (uses cookies for session ID)
- Cookie Name: ASP.NET_SessionId
- Expiration Type: Sliding
Method 1: Configuring Session Timeout in web.config
The most common and recommended way to set the session timeout is through the web.config file.
Basic Timeout Configuración
<configuration>
<system.web>
<sessionState
mode="InProc"
timeout="30"
cookieless="false"
cookieName="ASP.NET_SessionId" />
</system.web>
</configuration>
The timeout attribute is specified in minutes. Common values:
| Scenario | Recommended Timeout |
|---|---|
| High-security applications (banking) | 5-15 minutes |
| Standard web applications | 20-30 minutes |
| Internal/intranet applications | 30-60 minutes |
| Long-form data entry applications | 60-120 minutes |
| Kiosk or shared terminal applications | 5-10 minutes |
Complete sessionState Configuración
<configuration>
<system.web>
<sessionState
mode="InProc"
stateConnectionString="tcpip=127.0.0.1:42424"
sqlConnectionString="data source=.\SQLEXPRESS;Integrated Security=SSPI"
cookieless="false"
cookieName="ASP.NET_SessionId"
timeout="30"
regenerateExpiredSessionId="true"
sqlCommandTimeout="30"
useHostingIdentity="true">
</sessionState>
</system.web>
</configuration>
Key Attributes Explained
| Attribute | Description | Default |
|---|---|---|
mode | Where session data is stored (InProc, StateServer, SQLServer, Custom, Off) | InProc |
timeout | Minutes of inactivity before session expires | 20 |
cookieless | Whether to use cookies or URL rewriting for session ID | false |
cookieName | Name of the session cookie | ASP.NET_SessionId |
regenerateExpiredSessionId | Generate a new ID when an expired session ID is received | true |
sqlCommandTimeout | Timeout in seconds for SQL session state commands | 30 |
stateConnectionString | Connection string for StateServer mode | tcpip=loopbackaddress:42424 |
sqlConnectionString | Connection string for SQLServer mode | (none) |
Method 2: Configuring Session Timeout in IIS
The IIS configuration works alongside web.config and can override application-level settings in certain scenarios.
IIS Manager (GUI)
- Open IIS Manager (
inetmgr). - Select your application or site in the left panel.
- Double-click Session State in the Features View.
- Under Cookie Settings, configure the timeout value.
- Click Apply in the Actions panel.
IIS Application Pool Settings
The application pool idle timeout can cause sessions to be lost even when the session timeout has not been reached. By default, IIS app pools have a 20-minute idle timeout that shuts down the worker process.
To adjust the app pool idle timeout:
- Open IIS Manager.
- Click Application Pools in the left panel.
- Right-click your application pool and select Advanced Settings.
- Under Process Model, set Idle Time-out (minutes) to a value equal to or greater than your session timeout.
Via PowerShell (IIS module):
Import-Module WebAdministration
# View current app pool idle timeout
Get-ItemProperty "IIS:\AppPools\DefaultAppPool" -Name processModel.idleTimeout
# Set app pool idle timeout to 60 minutes
Set-ItemProperty "IIS:\AppPools\DefaultAppPool" -Name processModel.idleTimeout -Value "00:60:00"
# Disable idle timeout entirely (value of 0)
Set-ItemProperty "IIS:\AppPools\DefaultAppPool" -Name processModel.idleTimeout -Value "00:00:00"
IIS Configuración via applicationHost.config
For server-wide changes, edit the IIS applicationHost.config:
<!-- Located at: %windir%\System32\inetsrv\config\applicationHost.config -->
<system.applicationHost>
<applicationPools>
<add name="MyAppPool" managedRuntimeVersion="v4.0">
<processModel idleTimeout="01:00:00" />
</add>
</applicationPools>
</system.applicationHost>
Method 3: Programmatic Session Configuración
You can control session behavior directly in your C# code.
Setting Timeout in Global.asax
// Global.asax.cs
protected void Session_Start(object sender, EventArgs e)
{
// Set session timeout to 45 minutes for this session
Session.Timeout = 45;
}
Setting Timeout Per User Role
// Set different timeouts based on user role
protected void Application_PostAuthenticateRequest(object sender, EventArgs e)
{
if (HttpContext.Current.Session != null)
{
if (User.IsInRole("Administrator"))
{
Session.Timeout = 60; // Admins get 60 minutes
}
else if (User.IsInRole("DataEntry"))
{
Session.Timeout = 120; // Data entry users get 2 hours
}
else
{
Session.Timeout = 20; // Standard users get 20 minutes
}
}
}
Setting Timeout in a Controller or Page
// In an ASP.NET MVC Controller
public ActionResult Login(LoginModel model)
{
if (ModelState.IsValid && ValidateUser(model))
{
// Set session timeout after successful login
Session.Timeout = 30;
Session["UserName"] = model.Username;
Session["LoginTime"] = DateTime.UtcNow;
return RedirectToAction("Dashboard");
}
return View(model);
}
// In an ASP.NET Web Forms Page
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
// Check remaining session time
int timeoutMinutes = Session.Timeout;
Response.Write($"Session timeout: {timeoutMinutes} minutes");
}
}
Explicitly Abandoning a Session
// End the session immediately (e.g., on logout)
public ActionResult Logout()
{
Session.Abandon();
// Also clear the session cookie
if (Request.Cookies["ASP.NET_SessionId"] != null)
{
Response.Cookies["ASP.NET_SessionId"].Expires = DateTime.Now.AddDays(-1);
}
return RedirectToAction("Login");
}
Session State Modes
ASP.NET supports multiple session state storage modes. The choice of mode significantly affects performance, reliability, and timeout behavior.
InProc (In-Process)
<sessionState mode="InProc" timeout="30" />
- Storage: Server memory (IIS worker process).
- Rendimiento: Fastest. No serialization required.
- Durability: Volatile. Lost on app pool recycle, IIS restart, or server reboot.
- Scalability: Single server only. Not suitable for web farms or load-balanced environments.
- Best For: Small applications on a single server.
StateServer (Out-of-Process)
<sessionState mode="StateServer"
stateConnectionString="tcpip=192.168.1.100:42424"
timeout="30" />
- Storage: Separate Windows service (
ASP.NET State Service). - Rendimiento: Slower than InProc due to serialization and network overhead.
- Durability: Survives app pool recycles but lost on service or server restart.
- Scalability: Can be shared across multiple web servers.
- Requirement: All session objects must be serializable (
[Serializable]attribute). - Best For: Web farms that need shared session state without a database.
Enable the State Service:
# Start the ASP.NET State Service
Set-Service -Name aspnet_state -StartupType Automatic
Start-Service -Name aspnet_state
SQLServer
<sessionState mode="SQLServer"
sqlConnectionString="data source=SQLServer01;Integrated Security=SSPI"
timeout="30"
sqlCommandTimeout="30" />
- Storage: SQL Server database.
- Rendimiento: Slowest due to database round-trips.
- Durability: Fully persistent. Survives all restarts.
- Scalability: Excellent. Supports large web farms.
- Requirement: All session objects must be serializable. SQL Server session database must be configured.
- Best For: Enterprise applications, web farms, high-availability environments.
Setting up the SQL Server session database:
# Run the ASP.NET SQL Server registration tool
aspnet_regsql.exe -S SQLServer01 -E -ssadd -sstype p
The -sstype parameter options:
| Value | Description |
|---|---|
t | Temporary database (tempdb). Lost on SQL restart. |
p | Persistent database (ASPState). Survives SQL restart. |
c | Custom database name specified with -d parameter. |
Custom Session State Provider
<sessionState mode="Custom" customProvider="RedisSessionProvider" timeout="30">
<providers>
<add name="RedisSessionProvider"
type="Microsoft.Web.Redis.RedisSessionStateProvider"
host="localhost"
port="6379"
accessKey=""
ssl="false" />
</providers>
</sessionState>
Custom providers allow you to use Redis, MongoDB, DynamoDB, or any other backing store.
Sliding vs Absolute Expiration
Sliding Expiration (Default)
ASP.NET uses sliding expiration by default. The session timeout resets with every request. If the timeout is 30 minutes and the user makes a request at minute 29, the session is extended for another 30 minutes.
This is the built-in behavior and does not require any additional configuration.
Implementing Absolute Expiration
ASP.NET does not natively support absolute session expiration, but you can implement it:
// Global.asax.cs - Implement absolute session expiration
protected void Session_Start(object sender, EventArgs e)
{
Session["AbsoluteExpiry"] = DateTime.UtcNow.AddHours(8);
}
protected void Application_AcquireRequestState(object sender, EventArgs e)
{
if (HttpContext.Current.Session != null &&
Session["AbsoluteExpiry"] != null)
{
DateTime expiryTime = (DateTime)Session["AbsoluteExpiry"];
if (DateTime.UtcNow > expiryTime)
{
Session.Abandon();
Response.Redirect("~/SessionExpired.aspx");
}
}
}
Hybrid Approach (Sliding with Maximum Lifetime)
// Combine sliding expiration with an absolute maximum
protected void Session_Start(object sender, EventArgs e)
{
Session.Timeout = 30; // 30-minute sliding window
Session["MaxSessionLifetime"] = DateTime.UtcNow.AddHours(12); // 12-hour hard limit
}
protected void Application_AcquireRequestState(object sender, EventArgs e)
{
if (HttpContext.Current.Session != null &&
Session["MaxSessionLifetime"] != null)
{
DateTime maxLifetime = (DateTime)Session["MaxSessionLifetime"];
if (DateTime.UtcNow > maxLifetime)
{
Session.Clear();
Session.Abandon();
Response.Redirect("~/Login.aspx?reason=maxlifetime");
}
}
}
ASP.NET Core Session Configuración
For applications using ASP.NET Core, session configuration is done differently through the middleware pipeline.
Startup.cs / Program.cs Configuración
// Program.cs (ASP.NET Core 6+)
var builder = WebApplication.CreateBuilder(args);
// Add session services
builder.Services.AddDistributedMemoryCache(); // Use in-memory cache for development
builder.Services.AddSession(options =>
{
options.IdleTimeout = TimeSpan.FromMinutes(30);
options.Cookie.HttpOnly = true;
options.Cookie.IsEssential = true;
options.Cookie.Name = ".MyApp.Session";
options.Cookie.SecurePolicy = CookieSecurePolicy.Always;
});
var app = builder.Build();
// Add session middleware (must be after routing and before endpoints)
app.UseSession();
app.MapControllers();
app.Run();
Using Redis for Distributed Sessions in ASP.NET Core
// Program.cs
builder.Services.AddStackExchangeRedisCache(options =>
{
options.Configuration = "localhost:6379";
options.InstanceName = "MyApp_";
});
builder.Services.AddSession(options =>
{
options.IdleTimeout = TimeSpan.FromMinutes(30);
options.Cookie.HttpOnly = true;
options.Cookie.IsEssential = true;
});
Using SQL Server for Distributed Sessions in ASP.NET Core
// Program.cs
builder.Services.AddDistributedSqlServerCache(options =>
{
options.ConnectionString = builder.Configuration.GetConnectionString("SessionDb");
options.SchemaName = "dbo";
options.TableName = "Sessions";
options.ExpiredItemsDeletionInterval = TimeSpan.FromMinutes(30);
});
builder.Services.AddSession(options =>
{
options.IdleTimeout = TimeSpan.FromMinutes(30);
});
Create the SQL Server cache table:
dotnet sql-cache create "Server=.;Database=MyAppDb;Trusted_Connection=True;" dbo Sessions
Solución de Problemas Session Timeout Issues
Sessions Expiring Prematurely
Common causes and solutions:
-
App Pool Recycling: The IIS app pool recycles by default every 1740 minutes (29 hours) or when idle for 20 minutes. InProc sessions are destroyed on recycle.
- Fix: Increase the idle timeout, use StateServer or SQLServer mode, or disable recycling for the app pool.
-
Antivirus Scanning: Some antivirus software scans the ASP.NET temporary files folder, causing app domain restarts.
- Fix: Exclude the ASP.NET temp folder from antivirus scanning:
C:\Windows\Microsoft.NET\Framework64\v4.0.30319\Temporary ASP.NET Files\
- Fix: Exclude the ASP.NET temp folder from antivirus scanning:
-
Web.config or Bin Changes: Any modification to
web.configor files in thebinfolder triggers an automatic app domain restart.- Fix: Avoid writing to these directories at runtime.
-
Memory Pressure: Under high memory conditions, the .NET garbage collector may aggressively collect InProc session data.
- Fix: Monitor memory usage and consider switching to out-of-process session storage.
Debugging Session State
// Log session events in Global.asax
protected void Session_Start(object sender, EventArgs e)
{
System.Diagnostics.Debug.WriteLine(
$"Session Started: ID={Session.SessionID}, Time={DateTime.UtcNow}");
}
protected void Session_End(object sender, EventArgs e)
{
// Note: Session_End only fires for InProc mode
System.Diagnostics.Debug.WriteLine(
$"Session Ended: ID={Session.SessionID}, Time={DateTime.UtcNow}");
}
Resumen
ASP.NET session timeout can be configured through web.config (the sessionState element), IIS Manager settings, or programmatically in C# code. The default timeout is 20 minutes with sliding expiration. Choose the appropriate session state mode based on your application requirements: InProc for single-server simplicity and speed, StateServer for multi-server environments without database overhead, or SQLServer for full persistence and web farm scalability. Always ensure the IIS application pool idle timeout is equal to or greater than your session timeout to prevent premature session loss.