• Resolved mmdrzw122

    (@mmdrzw122)


    Hello LiteSpeed Support Team,

    I am reporting a rather unusual LSCache for WordPress caching behavior and would appreciate a detailed explanation from the LiteSpeed team, as well as guidance on whether there is a supported way to achieve the desired behavior without custom workarounds.

    The use case is very simple:

    I have a WooCommerce/WordPress site where all publicly accessible content is identical for guests and logged-in non-admin users.

    There is no user-specific content on the public-facing pages.

    There is no cart counter, username, personalized greeting, account information, customer-specific pricing, or any other user-specific fragment in the public header or public page content.

    The genuinely private areas are already excluded from caching, including:

    • Cart
    • Checkout
    • My Account
    • Authentication pages
    • Wishlist

    The goal is therefore:

    Guest → Public Cache
    Logged-in non-admin → the exact same Public Cache
    Administrator → optionally a separate variation
    Cart / Checkout / My Account / Auth / Wishlist → remain completely uncached

    I am intentionally NOT looking for Private Cache and I do NOT want ESI for this use case.

    The desired architecture is simply:

    Guest + Logged-in Non-Admin

    Same Public Cache Object

    while genuinely private pages remain uncached.Environment / configuration

    The site is using:

    • WordPress
    • WooCommerce
    • Woodmart theme
    • LiteSpeed Web Server Enterprise
    • LiteSpeed Cache for WordPress
    • ESI currently OFF
    • “Cache Logged-in Users” currently OFF

    The site already has working public caching for guests.

    Guest caching is not the problem.

    The problem is specifically how LSCache handles logged-in users when they should logically be identical to guests.The original behavior

    With:

    Cache Logged-in Users = ON

    logged-in users receive Private Cache behavior.

    That is not what I want.

    Private Cache is unnecessary for this site because the public pages are not personalized.

    So I disabled:

    Cache Logged-in Users = OFF

    After doing that, the Private Cache behavior disappeared, which is expected.

    However, the logged-in requests then became uncached:

    Guest:
    Public Cache → working normally

    Logged-in:
    No Cache

    This is also consistent with the current LSCache behavior.

    From the current LSCache source, I understand that when a user is logged in, ESI is disabled, and private logged-in caching is disabled, LSCache explicitly marks the request as non-cacheable with the reason “logged in user”.

    The relevant current source behavior is essentially:

    • logged-in + ESI OFF + Cache Logged-in ON → private cache
    • logged-in + ESI OFF + Cache Logged-in OFF → no cache

    This appears to be intentional behavior rather than a WooCommerce or Woodmart bug.

    This is precisely where my use case differs from the normal assumption:

    I am deliberately asking LSCache to treat a logged-in non-admin exactly like a guest for public pages because the generated public content is the same.Important discovery: _lscache_vary

    During investigation I found that logged-in requests receive a cookie similar to:

    _lscache_vary=admin_bar:1;logged-in:1

    while a normal guest request does not have this logged-in vary state.

    This is understandable given the current LSCache implementation.

    The current source explicitly adds:

    logged-in:1

    for logged-in users.

    It can also add:

    admin_bar:1

    depending on the show_admin_bar_front user option.

    The current source then applies the litespeed_vary filter before hashing the vary data.

    This led to the discovery that there are really two separate problems:

    1. Logged-in users are classified as non-cacheable when ESI and Private Logged-in Cache are both disabled.
    2. Logged-in users also receive a different _lscache_vary state, which causes them to use a different cache variation from guests.

    These two behaviors are extremely important for this use case.Testing with Force Public Cache

    I then tested the built-in:

    “Force Public Cache URIs”

    functionality.

    For example, I tested public pages such as:

    /privacy-terms/

    The result was very interesting.

    For a logged-in user, the response showed:

    X-LiteSpeed-Cache-Control: public,max-age=1209600

    so the Force Public mechanism clearly worked and the response was allowed to become publicly cacheable.

    However, the logged-in request still behaved as a separate cache variation.

    For example:

    Guest:

    X-LiteSpeed-Cache: miss

    then subsequent guest request:

    X-LiteSpeed-Cache: hit

    Logged-in:

    X-LiteSpeed-Cache: miss

    then subsequent logged-in request:

    X-LiteSpeed-Cache: hit

    This strongly indicated that both requests were publicly cached but were not sharing the same cache object.

    In other words:

    Guest → Public Object A
    Logged-in → Public Object B

    instead of:

    Guest + Logged-in → Public Object A

    This distinction is critical.

    Force Public solved the “can this logged-in request be cached?” problem, but did not by itself solve the “can it use the exact same cache variation as the guest?” problem.

    This also appears consistent with LiteSpeed’s cache-vary architecture, where cache varies are part of the cache key and multiple publicly cached versions can exist for the same URI.Admin Bar investigation

    Another discovery was that logged-in users could receive:

    _lscache_vary=admin_bar:1;logged-in:1

    even when the Admin Bar was not visibly displayed to normal users.

    The current LSCache source checks the WordPress user option:

    show_admin_bar_front

    and considers the admin bar active when that option is false/unset or explicitly true.

    I therefore also disabled the frontend Admin Bar for non-admin users while preserving the administrator’s behavior.

    This removed the unnecessary Admin Bar variation for regular users, but the core logged-in:1 distinction still remained.

    So the Admin Bar was not the fundamental issue.A key experiment: litespeed_vary_no

    I then investigated the official LSCache API and tested:

    litespeed_vary_no

    The idea was to tell LSCache not to create/use a vary for the current page.

    The response showed:

    X-LiteSpeed-Cache-Control: public,no-vary,max-age=1209600

    which proves the API was being executed.

    However, the behavior was not suitable when used in the first implementation.

    In one test, the logged-in request continued to MISS repeatedly rather than converging cleanly onto the guest object.

    More importantly, I observed that indiscriminately disabling the entire vary state can interfere with legitimate variations such as the administrator variation.

    This made it clear that simply disabling all varies is too blunt for this use case.

    I do not want to remove all Vary functionality.

    I specifically want:

    Guest
    and
    logged-in non-admin

    to share the same public cache variation,

    while retaining the ability for an Administrator variation to remain separate if desired.

    That distinction is very important.The cache lookup timing is also important

    One of the hardest parts of this investigation was understanding when _lscache_vary matters.

    My understanding is that the web server performs the initial cache lookup before WordPress/PHP executes.

    Therefore, if the browser arrives with:

    _lscache_vary=admin_bar:1;logged-in:1

    the server can perform the cache lookup using that variation before PHP has an opportunity to change anything.

    This explains a particularly confusing behavior:

    If the guest cache is already warm and a logged-in user still has the old vary cookie, the logged-in request can MISS even though the guest object already exists.

    PHP then runs.

    If the code causes the vary cookie to disappear from the response, subsequent requests can converge toward the guest cache variation, but that first request was already looked up under the logged-in vary state.

    Likewise, if the destination page is cold, the logged-in request can MISS first, PHP runs, and the page may then become cacheable if Force Public applies.

    This behavior makes the distinction between:

    • cache lookup key
    • response cacheability
    • response Set-Cookie
    • subsequent browser requests

    extremely important.Current successful workaround

    After several experiments, I found one workaround that finally produces the behavior I actually want.

    The workaround does NOT modify the WordPress authentication cookie.

    It only removes the LiteSpeed-specific:

    _lscache_vary

    cookie from the response for logged-in non-admin users.

    The actual WordPress authentication cookie:

    wordpress_logged_in_*

    remains untouched.

    This does not log the user out because _lscache_vary is not the authentication cookie.

    The result is that once the LiteSpeed vary cookie is no longer sent by the browser, the logged-in non-admin request can be treated like the guest request from the cache-key perspective.

    The effective model becomes:

    Guest:
    no logged-in vary cookie
    → guest/public cache variation

    Logged-in non-admin:
    no _lscache_vary
    → same public cache variation

    Administrator:
    still allowed to retain the administrator variation

    This workaround finally gives us the behavior we wanted.Another important observation: logged-in users need Force Public for first-time cache warming

    There is another subtle but important part of this use case.

    With:

    Cache Logged-in Users = OFF
    ESI = OFF

    a logged-in request is normally marked non-cacheable.

    Therefore, if a logged-in user is the first person to request a cold public page, that request does not normally warm the cache.

    To allow logged-in users to warm public pages as well, I have to use:

    “Force Public Cache URIs”

    for the public URLs I actually want cached.

    This is expected from the current design: Force Public is what overrides the normal non-cacheable condition for the logged-in request.

    So the desired final configuration becomes approximately:

    Cache Logged-in Users = OFF
    ESI = OFF

    Public pages:
    Force Public Cache

    Private pages:
    Do Not Cache

    Logged-in non-admin:
    LiteSpeed vary cookie suppressed

    Administrator:
    optional separate variation retainedOur current “Do Not Cache” rules

    The following private URL prefixes are explicitly excluded from caching:

    ^/checkout

    ^/cart

    ^/my-account

    ^/auth

    ^/wishlist

    The intention is that these pages remain non-cacheable for both guests and logged-in users.

    The custom workaround does not call any Force Cache or Set Cacheable function on these pages.

    It only changes the LiteSpeed vary cookie behavior.

    This distinction is important because I do NOT want this workaround to accidentally override the site’s genuine no-cache rules.What I believe would be the ideal native LiteSpeed solution

    I would strongly prefer not to maintain a custom cookie-manipulation workaround indefinitely.

    What I really want LiteSpeed Cache for WordPress to support natively is something conceptually like:

    “Treat logged-in users as the default public cache group when their public-facing output is identical to the guest view.”

    For example:

    Cache Mode:

    Guest + Logged-in Non-Admin
    → same public cache variation

    Administrator
    → optional separate public variation

    Private URLs
    → still completely uncached

    This would be much cleaner than forcing customers to discover and work around:

    • Private Cache
    • ESI
    • logged-in:1
    • admin_bar:1
    • _lscache_vary
    • Force Public
    • cache-key behavior before PHP
    • and custom Set-Cookie manipulation

    just to achieve “logged-in user receives the same public page as an anonymous visitor.”Why I am reporting this as a potential product/design issue

    I understand why LSCache is conservative.

    For most WordPress sites, logged-in users genuinely have different content.

    Private Cache and ESI are therefore sensible and valuable features.

    But there is an important class of sites where logged-in users have no personalized public-page content whatsoever.

    For those sites, the current behavior creates a rather surprising situation:

    The page is publicly cacheable for guests.

    The page is visually and functionally identical for logged-in non-admin users.

    Yet:

    • Private Cache is unnecessary.
    • ESI is unnecessary.
    • Logged-in Cache OFF causes No Cache.
    • Force Public is required to override the logged-in no-cache rule.
    • _lscache_vary creates a separate variation.
    • And the administrator/user-state variation has to be carefully preserved.

    This is a considerable amount of complexity for what should logically be a very simple caching scenario.

    Even more importantly, a user who does not deeply understand the LSCache vary architecture could easily create an unsafe configuration while trying to solve it.

    For example, blindly removing all Vary information can potentially cause an administrator-specific public response to become shared with normal visitors.

    That is exactly the kind of thing I would like LiteSpeed to make impossible or at least much harder to do incorrectly.My request to LiteSpeed

    Could you please review this use case and confirm the intended/correct supported mechanism?

    Specifically, I would like to know:

    1. Is there an officially supported way to make a logged-in non-admin user use the exact same public cache variation as a guest, while retaining a separate variation for administrators if required?
    2. Is removing _lscache_vary for logged-in non-admin users a safe and supported approach, or is there a better server/plugin-level mechanism intended for this?
    3. Is there a supported way to configure LSCache so that:
      • logged-in non-admin = default public cache group
      • administrator = optional separate public variation
      • private WooCommerce pages = still uncached
    4. Does LiteSpeed consider it correct that:
      • Cache Logged-in Users = OFF
      • ESI = OFF
      • logged-in user
        results in explicit NO CACHE even when the page is otherwise completely public?
    5. Would you consider adding a dedicated setting such as:
      “Share Public Cache with Logged-in Users”
      or an equivalent safe mechanism?

    Ideally such a setting would allow the plugin/server itself to handle the cache lookup correctly rather than requiring users to manipulate _lscache_vary from PHP.Why a native solution would be valuable

    This is not just a request for one site.

    The underlying use case is quite common:

    • informational sites with optional accounts
    • WooCommerce shops with no user-specific public pricing
    • stores where the cart/account/checkout are private but product/catalog pages are completely public
    • membership systems where public pages remain identical for everyone
    • sites that authenticate users but do not personalize the public frontend

    In those environments, it would be extremely useful if LiteSpeed could natively express:

    “This user is logged in, but for this public page they should be treated as an anonymous/public-cache visitor.”

    That would avoid custom PHP, cookie manipulation, fragile interactions with Vary, and the possibility of users accidentally exposing administrator-specific content.

    I would sincerely encourage the LiteSpeed team to consider improving this behavior or documentation so that other users do not have to spend hours reverse-engineering the interaction between logged-in detection, Private Cache, ESI, Vary Groups, _lscache_vary, and Force Public Cache.Summary of the investigation

    The final behavior we are trying to achieve is:

    Guest:
    → Public Cache

    Logged-in non-admin:
    → exactly the same Public Cache

    Administrator:
    → optional separate public variation

    Cart:
    → No Cache

    Checkout:
    → No Cache

    My Account:
    → No Cache

    Auth:
    → No Cache

    Wishlist:
    → No Cache

    ESI:
    → OFF

    Private Logged-in Cache:
    → OFF

    The current LSCache implementation appears to support the individual pieces of this architecture, but not in one clean configuration.

    The current source confirms that logged-in detection adds logged-in:1 to the default vary and that, with ESI disabled and Private Logged-in Cache disabled, logged-in requests are explicitly marked non-cacheable.

    The current Vary architecture also allows multiple public cache versions, which explains why simply making the logged-in request public does not necessarily make it share the exact same public object as the guest.

    I would greatly appreciate any clarification from the LiteSpeed team on the officially supported solution, and especially any recommendation that avoids custom manipulation of _lscache_vary.

    Thank you for taking the time to look into this.

    Best regards

Viewing 2 replies - 1 through 2 (of 2 total)
  • Plugin Support qtwrk

    (@qtwrk)

    for 1) and 3) no , it is not possible with current plugin logic

    for 2) this cookie is used for plugin to vary login, not login case , which is most critical one

    for 4) , yes , if you have that configuration combo , it will result login user get no-cache

    for 5) , as much as I would love to help , but unfortunately I don’t think it is going to happen.

    this is very unique case , for all these years I only have encountered like handful times , and doing things like this to this vary carries certain risk and complication , vary is basically like one of the core functions of plugin.

    and also, I think you can probably use rewrite rule to achieve your goal , publicly cache everything , exclude certain URI and exclude certain cookies.

    Plugin Support qtwrk

    (@qtwrk)

    since you have created a ticket already, I will then close this topic , please reply to your ticket if you have any further comments.

Viewing 2 replies - 1 through 2 (of 2 total)

You must be logged in to reply to this topic.