Sessions
Documentation / Sessions / Session protection

Session protection

Automatic protection — `user_id`

Any session containing the user_id key is treated as authenticated and will never be removed under memory pressure (only expires normally).

This key is inserted automatically by Runique's authentication system on login.


Manual protection — `session_active`

To protect a high-value anonymous session (cart, multi-step form, wizard), use protect_session:

use runique::prelude::*;

// Protect the session for 30 minutes
protect_session(&session, 60 * 30).await?;

The session_active key stores a future Unix timestamp. Protection expires automatically at that date — no manual cleanup needed.

To remove protection explicitly:

unprotect_session(&session).await?;

Protection logic

is_protected(record) = true if:
  - record contains "user_id"
  - OR record contains "session_active" with a future timestamp

Use case — protecting a shopping cart

use runique::prelude::*;

pub async fn add_to_cart(request: Request) -> AppResult<Response> {
    // The item comes from the URL: /cart/add?item=42
    let mut cart: Vec<String> = request.session.get("cart").await?.unwrap_or_default();
    if let Some(item) = request.get_query("item") {
        cart.push(item.to_string());
    }
    request.session.insert("cart", &cart).await?;

    // Protect the session for 2h against emergency cleanup
    protect_session(&request.session, 60 * 60 * 2).await?;

    Ok(Redirect::to("/cart").into_response())
}

pub async fn checkout_complete(request: Request) -> AppResult<Response> {
    // Empty the cart and remove the protection
    request.session.remove::<Vec<String>>("cart").await?;
    unprotect_session(&request.session).await?;

    Ok(Redirect::to("/confirmation").into_response())
}