# Refresh panel app is creating new session

**URL:** <https://discourse.holoviz.org/t/refresh-panel-app-is-creating-new-session/6839>\
**Category:** Panel\
**Created:** [February 6, 2024, 3:46pm UTC](https://discourse.holoviz.org/t/refresh-panel-app-is-creating-new-session/6839 "2024-02-06T15:46:20Z")\
**Posts on this page:** 10\
**Page:** 1

<div class="post-metadata">

**Author:** ![nemesis00sam](https://discourse.holoviz.org/user_avatar/discourse.holoviz.org/nemesis00sam/32/5463_2.png) [@nemesis00sam](https://discourse.holoviz.org/u/nemesis00sam)\
**Post date:** [February 6, 2024, 3:46pm UTC](https://discourse.holoviz.org/t/refresh-panel-app-is-creating-new-session/6839/1 "2024-02-06T15:46:20Z")

</div>

Hi;

First of all, I want to thank all of you. I’m fan of panel.  
I’m facing a problem. I built a chat app but when I refresh it, it is creating new session. But this happens when I launch the app with following command.

`nohup panel serve --port 4002 chat.py --session-token-expiration 1000 --allow-websocket-origin=ip:4002 > /dev/null 2>&1 &`

But if I use the **pn.serve(dashboard\_object,port=4002)** command, it works properly. When I refresh, I can see the previous chat prompts.

I didn’t paste my code because I think if I add some parameter to **panel serve** , it can work. I need your help to fix my command line expression. If you think it is a bug, let me know. I will share a minimal example.

Thanks in advance.

---

<div class="post-metadata">

**Author:** ![ahuang11](https://discourse.holoviz.org/user_avatar/discourse.holoviz.org/ahuang11/32/4947_2.png) [@ahuang11](https://discourse.holoviz.org/u/ahuang11)\
**Post date:** [February 7, 2024, 4:43am UTC](https://discourse.holoviz.org/t/refresh-panel-app-is-creating-new-session/6839/2 "2024-02-07T04:43:07Z")

</div>

Likely it creates a new session because you have `.show()` somewhere in your code.

---

<div class="post-metadata">

**Author:** ![nemesis00sam](https://discourse.holoviz.org/user_avatar/discourse.holoviz.org/nemesis00sam/32/5463_2.png) [@nemesis00sam](https://discourse.holoviz.org/u/nemesis00sam)\
**Post date:** [February 7, 2024, 4:48am UTC](https://discourse.holoviz.org/t/refresh-panel-app-is-creating-new-session/6839/3 "2024-02-07T04:48:58Z")

</div>

Hi @ahuang11, I will share an example with you today or tomorrow . There is no .show() in my code. As existing code is very long, it will not be a good example for you. I will try to create small one from my code. Thanks for quick response.

---

<div class="post-metadata">

**Author:** ![nemesis00sam](https://discourse.holoviz.org/user_avatar/discourse.holoviz.org/nemesis00sam/32/5463_2.png) [@nemesis00sam](https://discourse.holoviz.org/u/nemesis00sam)\
**Post date:** [February 7, 2024, 3:12pm UTC](https://discourse.holoviz.org/t/refresh-panel-app-is-creating-new-session/6839/4 "2024-02-07T15:12:42Z")

</div>

Hi @ahuang11

I tested following code. I see the similar problem with following terminal command.

panel serve --port 8004 replicate\_error.py --check-unused-sessions 5000 --unused-session-lifetime 1000

```auto
import panel as pn
import param
import time

pn.extension(sizing_mode='stretch_width')

css = """
.bk-panel-models-markup-HTML.markdown.message {
  font-size: 16px; /* Or your desired font size */
}
.bk-input {
    font-size: 16px;
}

.bk-btn.bk-btn-default {
    font-size: 16px;
}
"""

pn.config.raw_css.append(css)

class Chatbot(param.Parameterized):

    pn.chat.ChatMessage(timestamp_format="%b %d, %Y %I:%M %p")

    async def callback(self, contents: str, user: str, instance: pn.chat.ChatInterface):
        instance.placeholder_text = (
                        f"Hang tight! Answer will be ready soon."
                    )
        time.sleep(3)
        message = ""
        for char in "Echoing User: " + contents:
            time.sleep(0.1)
            message += char
            yield message

    def create_layout(self):
        self.chat_interface = pn.chat.ChatInterface(
            callback=self.callback,
            placeholder_text="Waiting for reply...",
            placeholder_threshold=0.1,
            message_params=dict(
                default_avatars={"System": "&#128301;", "User": "👤"},
                reaction_icons={"like": "thumb-up"},
            ),
            show_rerun=False,
            show_undo=False,
            show_clear=True,
            sizing_mode="stretch_width",
            view_latest=True,
            scroll_button_threshold=2,
            auto_scroll_limit=20000,
        )

        _stylesheets = """
bk-panel-models-markup-HTML markdown message {
  font-size: 6px; /* Or your desired font size */
}
"""

    
        self.chat_interface.send(
            {"object":"Wait for my signal."
             },
            user="System",
            respond=False
        )

        str_pane = pn.pane.Str('Chatbot can make mistakes. Cross-checking answers is recommended.',sizing_mode='stretch_width',
                                styles={'font-size': '12px','color': 'gray', 'text-align': 'center', 'justify-content':'center','margin-top':'20px',
                                        'display':'flex', 'align-items':'center'})
        
        template = pn.template.BootstrapTemplate(
            title="Title",
            header_color = "black",
            sidebar=[],
            main=[pn.Column(self.chat_interface,str_pane)],
            header_background = "black"
        )

        return template
    
dashboard_object = Chatbot().create_layout()
#pn.serve(dashboard_object,port=4002) 
dashboard_object.servable(title="Report")

```

---

<div class="post-metadata">

**Author:** ![nemesis00sam](https://discourse.holoviz.org/user_avatar/discourse.holoviz.org/nemesis00sam/32/5463_2.png) [@nemesis00sam](https://discourse.holoviz.org/u/nemesis00sam)\
**Post date:** [February 9, 2024, 4:21am UTC](https://discourse.holoviz.org/t/refresh-panel-app-is-creating-new-session/6839/5 "2024-02-09T04:21:18Z")

</div>

Hello everyone,

Have you had a chance to review the code. I’m are having a bit of trouble because it is a product in production. Thank you in advance for your support.

---

<div class="post-metadata">

**Author:** ![ahuang11](https://discourse.holoviz.org/user_avatar/discourse.holoviz.org/ahuang11/32/4947_2.png) [@ahuang11](https://discourse.holoviz.org/u/ahuang11)\
**Post date:** [February 9, 2024, 6:04pm UTC](https://discourse.holoviz.org/t/refresh-panel-app-is-creating-new-session/6839/6 "2024-02-09T18:04:32Z")

</div>

I think I misunderstood. Do you mean creating a new session as in, when you refresh, all your chat history is gone? If so, you need to sync it up with user and reload the chat history based on the cache [Sync Widgets and URL — Panel v1.3.8](https://panel.holoviz.org/how_to/state/examples/sync_url.html)  
[Configuring Basic Authentication — Panel v1.3.8](https://panel.holoviz.org/how_to/authentication/basic.html)

---

<div class="post-metadata">

**Author:** ![nemesis00sam](https://discourse.holoviz.org/user_avatar/discourse.holoviz.org/nemesis00sam/32/5463_2.png) [@nemesis00sam](https://discourse.holoviz.org/u/nemesis00sam)\
**Post date:** [February 13, 2024, 8:02am UTC](https://discourse.holoviz.org/t/refresh-panel-app-is-creating-new-session/6839/7 "2024-02-13T08:02:18Z")

</div>

Thanks. But why is pn.serve(dashboard\_object,port=4002) loading existing chatbot history when we refresh. What is the difference between pn.serve and panel serve?

---

<div class="post-metadata">

**Author:** ![Alex-Wenner-FHR](https://discourse.holoviz.org/user_avatar/discourse.holoviz.org/alex-wenner-fhr/32/7225_2.png) [@Alex-Wenner-FHR](https://discourse.holoviz.org/u/Alex-Wenner-FHR)\
**Post date:** [September 8, 2025, 1:49pm UTC](https://discourse.holoviz.org/t/refresh-panel-app-is-creating-new-session/6839/8 "2025-09-08T13:49:04Z")

</div>

@ahuang11 I actually have this same issue. It seems like if I stay on one page, reload 10 times, I have 10 sessions that never get cleaned up, that just continue to increase memory until whatever compute runs out… I am using pn.serve, have the `check_unused_sessions_milliseconds` and `unused_session_lifetime_milliseconds` specified but they don’t seem to do anything.

---

<div class="post-metadata">

**Author:** ![ahuang11](https://discourse.holoviz.org/user_avatar/discourse.holoviz.org/ahuang11/32/4947_2.png) [@ahuang11](https://discourse.holoviz.org/u/ahuang11)\
**Post date:** [September 8, 2025, 3:21pm UTC](https://discourse.holoviz.org/t/refresh-panel-app-is-creating-new-session/6839/9 "2025-09-08T15:21:12Z")

</div>

Can you submit a GitHub issue? I am not too familiar with pn.serve, and I think panel serve is more robust.

---

<div class="post-metadata">

**Author:** ![dwr-psandhu](https://discourse.holoviz.org/user_avatar/discourse.holoviz.org/dwr-psandhu/32/531_2.png) [@dwr-psandhu](https://discourse.holoviz.org/u/dwr-psandhu)\
**Post date:** [September 25, 2025, 3:55pm UTC](https://discourse.holoviz.org/t/refresh-panel-app-is-creating-new-session/6839/10 "2025-09-25T15:55:12Z")

</div>

Just linking the issue opened by @Alex-Wenner-FHR

> <https://github.com/holoviz/panel/issues/8189>
>
> \#### ALL software version info
> \- panel 1.7.5 and 1.8.0
> \- python 3.12 - container… environment
> \- bokeh - 3.7.3
> 
> 
> 
> 
> \#### Expected
> 
> When using pn.serve to serve a multi-page application, I would expect to go to one page and have a new session created. When I go to another page, I would expect either that session to be removed. Which it is depending on the culling period. However, I would expect that memory consumed by other sessions to be re allocated. 
> 
> \#### Observed
> 
> When using pn.serve to serve a multi-page application, after the session culling occurs, no memory is re allocated back to the service running. It feels like this could eventually cause an OOM if several different users access the same application and have several sessions - although the sessions are removed the memory is never reclaimed. 
> 
> I could be missing something here so any thoughts help!
> 
> 
> \#### Complete, minimal, self-contained example code that reproduces the issue
> 
> \`\`\`python
> 
> 
> import panel as pn
> from typing import Any
> import json
> import random
> 
> \# Configure Panel with minimal extensions
> pn.extension(notifications=True)
> 
> def generate\_mock\_data(num\_items: int = 10000) -\> list\[dict\[str, Any\]\]:
> """Generate a large list of mock data to simulate memory-heavy content."""
> mock\_data = \[\]
> for i in range(num\_items):
> mock\_data.append({
> "id": i,
> "name": f"User {i}",
> "email": f"user{i}@example.com",
> "age": random.randint(18, 80),
> "city": random.choice(\["New York", "London", "Tokyo", "Paris", "Berlin", "Sydney"\]),
> "occupation": random.choice(\["Engineer", "Designer", "Manager", "Analyst", "Developer"\]),
> "salary": random.randint(30000, 150000),
> "active": random.choice(\[True, False\]),
> "metadata": {
> "created\_at": f"2023-{random.randint(1, 12):02d}-{random.randint(1, 28):02d}",
> "last\_login": f"2024-{random.randint(1, 12):02d}-{random.randint(1, 28):02d}",
> "preferences": {
> "theme": random.choice(\["light", "dark"\]),
> "notifications": random.choice(\[True, False\]),
> "language": random.choice(\["en", "es", "fr", "de"\])
> }
> }
> })
> return mock\_data
> 
> def create\_page\_a() -\> Any:
> """Page factory A - simulates lazy page loading with session info access and large mock data."""
> print("Page A factory called")
>     
> # Generate large mock data to exemplify memory-heavy page
> mock\_data = generate\_mock\_data(100000)
>     
> # Convert to JSON string for display (this will be large)
> json\_payload = json.dumps(mock\_data, indent=2)
>     
> # Create a Panel layout with the data
> data\_pane = pn.pane.JSON(json\_payload, name="Mock Data", height=600, sizing\_mode="stretch\_width")
>     
> return pn.Column(
> pn.pane.Markdown("# Page A\\nThis is page A content with large mock data."),
> pn.pane.Markdown(f"\*\*Total items:\*\* {len(mock\_data)}"),
> data\_pane,
> sizing\_mode="stretch\_width"
> )
> 
> def create\_page\_b() -\> Any:
> """Page factory B - simulates lazy page loading with session info access."""
> print("Page B factory called")
> return pn.pane.Markdown("# Page B\\nThis is page B content.")
> 
> def create\_home\_page() -\> Any:
> """Home page factory."""
> print("Home page factory called")
> return pn.pane.Markdown("""
> # Home Page
>     
> Navigate between pages to test session management:
> - \[Page A\](/page-a)
> - \[Page B\](/page-b)
> """)
> 
> \# Route mapping using lazy page factories
> apps = {
> "": create\_home\_page,
> "page-a": create\_page\_a,  
> "page-b": create\_page\_b,
> }
> 
> if \_\_name\_\_ == "\_\_main\_\_":
> 
> pn.state.on\_session\_created(lambda s: print(f"Session created: {s.\_\_dict\_\_}"))
> pn.state.on\_session\_destroyed(lambda s: print(f"Session destroyed: {s.\_\_dict\_\_}"))
> 
> pn.serve(
> apps, # type: ignore\[arg-type\]
> address="0.0.0.0", 
> port=5007,
> show=False,
> autoreload=False,
> dev=False,
> warm=True,
> allow\_websocket\_origin=\["\*"\],
> title="Session Management Repro",
> reuse\_session=True,
> check\_unused\_sessions\_milliseconds=5000, # Check every 5 seconds
> unused\_session\_lifetime\_milliseconds=5000, # Destroy after 5 seconds
> )
> \`\`\`
> 
> \`\`\`dockerfile
> FROM python:3.12
> WORKDIR "/app"
> COPY . .
> RUN pip install -r requirements.txt
> CMD \["python3", "-m", "minimal\_repro"\]
> \`\`\`
> 
> \- Docker Stats
> \<img width="802" height="68" alt="Image" src="https://github.com/user-attachments/assets/473c3711-6833-47e0-b127-4a77c094ff4c" /\>
> 
> I hit a certain point where the memory sort of plateaus if you will, but when sessions are destroyed, that memory is never re allocated back. Is this expected? 
> 
> 
> However if I open up localhost in several different tabs, memory just continues to increase and as mentioned, is never reclaimed. 
> 
> \<img width="791" height="63" alt="Image" src="https://github.com/user-attachments/assets/5362a2da-b92b-4d04-b48b-6b0150158699" /\>
> 
> Which in turns, means for long running applications they \_eventually\_ will hit an OOM.
