# dcc.Interval doesn't update data

**URL:** <https://community.plotly.com/t/dcc-interval-doesnt-update-data/78479>\
**Category:** Dash Python\
**Created:** [September 12, 2023, 12:13pm UTC](https://community.plotly.com/t/dcc-interval-doesnt-update-data/78479 "2023-09-12T12:13:59Z")\
**Posts on this page:** 18\
**Page:** 1

<div class="post-metadata">

**Author:** ![TemaTorg](https://avatars.discourse-cdn.com/v4/letter/t/4bbf92/32.png) [@TemaTorg](https://community.plotly.com/u/TemaTorg)\
**Post date:** [September 12, 2023, 12:13pm UTC](https://community.plotly.com/t/dcc-interval-doesnt-update-data/78479/1 "2023-09-12T12:13:59Z")

</div>

Hello colleagues!  
I’ve been using dash for over a year, but recently decided to join you because the projects have become more complex 🙂

I have a dashboard with graphs, filters, tables. I get the data from the own function “msg\_data()” - this is a pandas dataframe obtained using SQL. I need to update data with a certain period without restarting the project. Also I update the DatePickeRange component. I chose a solution using dcc.Interval(), but it doesn’t work correctly.

I’ll try to give an example of the main elements of my code:

```auto
DATA = msg_data()

app.layout = dbc.Container(
    children=[
        ...
        dcc.Graph(id='graph1'),
        dcc.DatePickerRange(id='picker_range', ... ),
        dcc.Interval(id='interval-component', interval=3*60*1000)
        ...
    ]
)

@app.callback(
    Output('picker_range', 'max_date_allowed'),
    Output('picker_range', 'end_date'),
    Output('picker_range', 'start_date'),
    Input('interval-component', 'n_intervals')
)
def update_data(n):
    if n:
        global DATA
        DATA = msg_data()
    day = datetime.date(datetime.now())
    s_day = day - timedelta(days=29)
    return day, day, s_day

@app.callback(
    Output('graph1', 'figure'),
    Input('picker_range', 'end_date'),
    Input('picker_range', 'start_date')
)
def create_graph(e_day, s_day):
    df = DATA
    ...
    return figure

```

If I launch the project and open it in the browser, the data is updated every 3 minutes and everything is fine. But if I open the browser after the night, I see that the **dates are correct** in DatePickerRange, but there is no data for the new day in the graphs and tables. I wait 3 minutes and it appear.

I do not understand what the problem is.  
Maybe the Interval component does not work without an observer (open browser)? How can I then trigger the component?  
Perhaps the second callback (create\_graph()) does not work offline?

The problem is that I have a project where I need to update data once every 24 hours and I don’t want to keep the browser open. I would also like to solve this without the windows task scheduler or Cron.

I also liked the idea of ​​using flask-caching with filesystem storage, but to do this I also need to trigger the function somehow

---

<div class="post-metadata">

**Author:** ![jhupiterz](https://sea2.discourse-cdn.com/flex024/user_avatar/community.plotly.com/jhupiterz/32/19435_2.png) [@jhupiterz](https://community.plotly.com/u/jhupiterz)\
**Post date:** [September 12, 2023, 1:56pm UTC](https://community.plotly.com/t/dcc-interval-doesnt-update-data/78479/2 "2023-09-12T13:56:42Z")

</div>

Hi @TemaTorg, could this be of any help: [Live Updates](https://dash.plotly.com/live-updates)?

Passing your layout as a function to make sure the layout is updated everytime to re-open your browser?

---

<div class="post-metadata">

**Author:** ![TemaTorg](https://avatars.discourse-cdn.com/v4/letter/t/4bbf92/32.png) [@TemaTorg](https://community.plotly.com/u/TemaTorg)\
**Post date:** [September 12, 2023, 2:08pm UTC](https://community.plotly.com/t/dcc-interval-doesnt-update-data/78479/3 "2023-09-12T14:08:19Z")

</div>

Hi, @jhupiterz , thank you for the idea, but this solution does not work.

In some of my projects, it takes 15 minutes to unload data from the database and this is a very long time for users. So I want to update the main dataframe once late at night.

---

<div class="post-metadata">

**Author:** ![jhupiterz](https://sea2.discourse-cdn.com/flex024/user_avatar/community.plotly.com/jhupiterz/32/19435_2.png) [@jhupiterz](https://community.plotly.com/u/jhupiterz)\
**Post date:** [September 12, 2023, 6:08pm UTC](https://community.plotly.com/t/dcc-interval-doesnt-update-data/78479/4 "2023-09-12T18:08:02Z")

</div>

I think it comes from the fact that your second callback, that updates your graph, uses the `DATA` that is defined on line 1 of your code. This line would only be executed when the program starts, [not when the page is re-loaded](https://dash.plotly.com/app-lifecycle).

Your `DatePickerRange` is being updated correctly because you redefine `DATA` in the associated callback, so `DATA` is being updated within the scope of your callback but isn’t stored anywhere.

To fix it, my guess would be that you can either:

1. update `DATA` inside your second callback based on your `DatePickerRange`, or
2. Store `DATA` from your first callback in a `dcc.Store` component that you can reuse as an input in your second callback.

---

<div class="post-metadata">

**Author:** ![TemaTorg](https://avatars.discourse-cdn.com/v4/letter/t/4bbf92/32.png) [@TemaTorg](https://community.plotly.com/u/TemaTorg)\
**Post date:** [September 12, 2023, 7:56pm UTC](https://community.plotly.com/t/dcc-interval-doesnt-update-data/78479/5 "2023-09-12T19:56:07Z")

</div>

Thank you for your answer.

I made an example based on your first sentence:

```auto
from dash import Dash, html, Input, Output, dcc
import dash_bootstrap_components as dbc
from datetime import datetime

DATA = datetime.now()

app = Dash( __name__ )
# app.config.prevent_initial_callbacks = True
app.layout = dbc.Container([
    dbc.Row(
        html.Div(id='time_area', children='some text')
    ),
    dbc.Row(
        dcc.DatePickerRange(id='picker_range')
    ),
    dcc.Interval(id='interval-component', interval=15*1000, n_intervals=0)
])

@app.callback(
    Output('picker_range', 'end_date'),
    Input('interval-component', 'n_intervals')
)
def update_data(n):
    # I don't want to count it twice after "run"
    if n > 0:
        global DATA
        DATA = datetime.now()
    day = datetime.date(datetime.now())
    return day

@app.callback(
    Output('time_area', 'children'),
    Input('picker_range', 'end_date')
)
def create_graph(e_day):
    df = DATA
    return df

if __name__ == ' __main__':
    app.run_server(debug=True)

```

If you launch the application, you can see the time in the upper left corner. I close the browser tab, wait a minute, open it again and see the old time until the interval works again.

I need a way to change data and save it when the application is closed. Now I’ll try dcc.Store().

---

<div class="post-metadata">

**Author:** ![jhupiterz](https://sea2.discourse-cdn.com/flex024/user_avatar/community.plotly.com/jhupiterz/32/19435_2.png) [@jhupiterz](https://community.plotly.com/u/jhupiterz)\
**Post date:** [September 12, 2023, 8:14pm UTC](https://community.plotly.com/t/dcc-interval-doesnt-update-data/78479/6 "2023-09-12T20:14:46Z")

</div>

> [@TemaTorg](#):
>
> ```auto
> from dash import Dash, html, Input, Output, dcc
> import dash_bootstrap_components as dbc
> from datetime import datetime
> 
> DATA = datetime.now()
> 
> app = Dash( __name__ )
> # app.config.prevent_initial_callbacks = True
> app.layout = dbc.Container([
> dbc.Row(
> html.Div(id='time_area', children='some text')
> ),
> dbc.Row(
> dcc.DatePickerRange(id='picker_range')
> ),
> dcc.Interval(id='interval-component', interval=15*1000, n_intervals=0)
> ])
> 
> @app.callback(
> Output('picker_range', 'end_date'),
> Input('interval-component', 'n_intervals')
> )
> def update_data(n):
> # I don't want to count it twice after "run"
> if n > 0:
> global DATA
> DATA = datetime.now()
> day = datetime.date(datetime.now())
> return day
> 
> @app.callback(
> Output('time_area', 'children'),
> Input('picker_range', 'end_date')
> )
> def create_graph(e_day):
> df = DATA
> return df
> 
> if __name__ == ' __main__':
> app.run_server(debug=True)
> 
> ```

So based on your example above, if in your second callback you replace `df = DATA` by `DATA = datetime.now()` then I think it does what you’re after, unless I didn’t get your issue.

---

<div class="post-metadata">

**Author:** ![TemaTorg](https://avatars.discourse-cdn.com/v4/letter/t/4bbf92/32.png) [@TemaTorg](https://community.plotly.com/u/TemaTorg)\
**Post date:** [September 12, 2023, 8:20pm UTC](https://community.plotly.com/t/dcc-interval-doesnt-update-data/78479/7 "2023-09-12T20:20:24Z")

</div>

Same problem 😢 After re-opening the browser tab, I see the old data.

```auto
from dash import Dash, html, Input, Output, dcc
import dash_bootstrap_components as dbc
from datetime import datetime

DATA = datetime.now()

app = Dash( __name__ )
app.layout = dbc.Container([
    dbc.Row(
        html.Div(id='time_area', children='some text')
    ),
    dbc.Row(
        dcc.DatePickerRange(id='picker_range')
    ),
    dcc.Interval(id='interval-component', interval=15 * 1000, n_intervals=0),
    dcc.Store(id='store', storage_type='local')
])

@app.callback(
    Output('picker_range', 'end_date'),
    Output('store', 'data'),
    Input('interval-component', 'n_intervals')
)
def update_data(n):
    # I don't want to count it twice after "run"
    if n > 0:
        global DATA
        DATA = datetime.now()
    day = datetime.date(datetime.now())
    return day, DATA

@app.callback(
    Output('time_area', 'children'),
    Input('store', 'data')
)
def create_graph(data):
    df = data
    return df

if __name__ == ' __main__':
    app.run_server(debug=True)

```

---

<div class="post-metadata">

**Author:** ![TemaTorg](https://avatars.discourse-cdn.com/v4/letter/t/4bbf92/32.png) [@TemaTorg](https://community.plotly.com/u/TemaTorg)\
**Post date:** [September 12, 2023, 8:24pm UTC](https://community.plotly.com/t/dcc-interval-doesnt-update-data/78479/8 "2023-09-12T20:24:40Z")

</div>

In a real working example, instead of datetime.now() in the DATA variable, I have a huge DataFrame that takes several minutes to count. Also, the create\_graph() function in the working project receives about 10 Input arguments (filters). Therefore, I separated the function of updating data and the function of creating graphs and tables.

---

<div class="post-metadata">

**Author:** ![jinnyzor](https://sea2.discourse-cdn.com/flex024/user_avatar/community.plotly.com/jinnyzor/32/21194_2.png) [@jinnyzor](https://community.plotly.com/u/jinnyzor)\
**Post date:** [September 12, 2023, 8:55pm UTC](https://community.plotly.com/t/dcc-interval-doesnt-update-data/78479/9 "2023-09-12T20:55:34Z")

</div>

Hello @TemaTorg,

What is updating your df in the background? Is it the app or is there a process outside of the app that will update the df?

Is there no data in the current day until whatever procedure updates the df?

---

<div class="post-metadata">

**Author:** ![TemaTorg](https://avatars.discourse-cdn.com/v4/letter/t/4bbf92/32.png) [@TemaTorg](https://community.plotly.com/u/TemaTorg)\
**Post date:** [September 12, 2023, 9:06pm UTC](https://community.plotly.com/t/dcc-interval-doesnt-update-data/78479/10 "2023-09-12T21:06:59Z")

</div>

Hello, @jinnyzor

> [@jinnyzor](#):
>
> What is updating your df in the background? Is it the app or is there a process outside of the app that will update the df?

This data is from a PostgreSQL database and it is updated very frequently.

> [@jinnyzor](#):
>
> Is there no data in the current day until whatever procedure updates the df?

No( I always check DB. We get a lot of new data every day.

---

<div class="post-metadata">

**Author:** ![jinnyzor](https://sea2.discourse-cdn.com/flex024/user_avatar/community.plotly.com/jinnyzor/32/21194_2.png) [@jinnyzor](https://community.plotly.com/u/jinnyzor)\
**Post date:** [September 12, 2023, 9:08pm UTC](https://community.plotly.com/t/dcc-interval-doesnt-update-data/78479/11 "2023-09-12T21:08:33Z")

</div>

What is updating the DF?

Not the database.

The DF is how the info is getting into the app.

* * *

Assuming that you are relying on the app to do this, the data will not be refreshed until there is a user on the app.

This is because of how callbacks work, they have to respond to a request from the client’s browser. To schedule tasks to update data independent, you’ll need to use something like crontab or a supervisor that will run and update your data on a system based time.

* * *

Currently, with updating your df based upon user queries will continuously spam your db the more users you have on the app.

What I do in my own app is I have stored procedures that perform all the heavy lifting into set tables, these tables are then picked up by a crontab job that runs on my server and inserts the table data into a db that is on the same server as the app.

Then I use this local data to update the info in the app.

stored proc → crontab job to pull data local → interval based local queries to update the users data

* * *

Others mention storing these dfs into local parquet files as well, which can be quicker to convert into dfs.

---

<div class="post-metadata">

**Author:** ![TemaTorg](https://avatars.discourse-cdn.com/v4/letter/t/4bbf92/32.png) [@TemaTorg](https://community.plotly.com/u/TemaTorg)\
**Post date:** [September 12, 2023, 9:27pm UTC](https://community.plotly.com/t/dcc-interval-doesnt-update-data/78479/12 "2023-09-12T21:27:01Z")

</div>

Thank you!

You are right. I wanted to update data using the application and without users on the page.

> [@jinnyzor](#):
>
> Currently, with updating your df based upon user queries will continuously spam your db the more users you have on the app.

Agree

I found an interesting example, maybe it will suit me:

```auto
import schedule
import time
import dash

app = dash.Dash( __name__ )

def run_dash_app():
    # Define the layout of the Dash app
    app.layout = dash.html.Div( ... )
    app.run_server(debug=True)

# Run the Dash app every 10 minutes
schedule.every(10).minutes.do(run_dash_app)

while True:
    schedule.run_pending()
    time.sleep(1)

```

---

<div class="post-metadata">

**Author:** ![jinnyzor](https://sea2.discourse-cdn.com/flex024/user_avatar/community.plotly.com/jinnyzor/32/21194_2.png) [@jinnyzor](https://community.plotly.com/u/jinnyzor)\
**Post date:** [September 12, 2023, 9:32pm UTC](https://community.plotly.com/t/dcc-interval-doesnt-update-data/78479/13 "2023-09-12T21:32:18Z")

</div>

That could indeed work. Let me know how it goes. 😃

My only concern is about running the app this way is how long it takes your data to query from your db. Could introduce some significant downtime.

Also, its not really a way to go about it if you are using a dedicated web server with a supervisor, as these would use gunicorn which has multiple workers.

---

<div class="post-metadata">

**Author:** ![TemaTorg](https://avatars.discourse-cdn.com/v4/letter/t/4bbf92/32.png) [@TemaTorg](https://community.plotly.com/u/TemaTorg)\
**Post date:** [September 13, 2023, 1:23pm UTC](https://community.plotly.com/t/dcc-interval-doesnt-update-data/78479/14 "2023-09-13T13:23:14Z")

</div>

Hello

Schedule doesn’t work as I expected. I made a small test script:

```auto
import time
from dash import Dash, html
from datetime import datetime
import schedule

app = Dash( __name__ )

def run_dash_app():
    print('--- run dash application ---')
    dt = datetime.now()
    print(dt)
    app.layout = html.Div(children=dt)
    app.run_server(debug=True)

schedule.every().minute.at(":30").do(run_dash_app)

while True:
    schedule.run_pending()
    time.sleep(1)

```

 ![schedule](https://us1.discourse-cdn.com/flex024/uploads/plot/original/3X/2/e/2e3a40aad48ea2e525929b12c8d6f04265339ba7.png)

It works twice and that’s it. Is there any way to stop the server before starting it?

---

<div class="post-metadata">

**Author:** ![jinnyzor](https://sea2.discourse-cdn.com/flex024/user_avatar/community.plotly.com/jinnyzor/32/21194_2.png) [@jinnyzor](https://community.plotly.com/u/jinnyzor)\
**Post date:** [September 13, 2023, 4:31pm UTC](https://community.plotly.com/t/dcc-interval-doesnt-update-data/78479/15 "2023-09-13T16:31:21Z")

</div>

Since it seems that you dont want to do this systematically, here are two python scripts to get you going:

app.py

```auto
from dash import Dash, html, Input, Output, dcc
import dash_bootstrap_components as dbc
from datetime import datetime
import json

DATA = datetime.now()

app = Dash( __name__ )
app.layout = dbc.Container([
    dbc.Row(
        html.Div(id='time_area', children='some text')
    ),
    dbc.Row(
        dcc.DatePickerRange(id='picker_range')
    ),
    dcc.Interval(id='interval-component', interval=15 * 1000, n_intervals=0),
    dcc.Store(id='store', storage_type='local')
])

@app.server.route('/updateDF', methods=['POST'])
def updateDF():
    global DATA
    DATA = datetime.now()
    return json.dumps({'status':'successful'})

@app.callback(
    Output('picker_range', 'end_date'),
    Output('store', 'data'),
    Input('interval-component', 'n_intervals')
)
def update_data(n):
    day = datetime.date(datetime.now())
    return day, DATA

@app.callback(
    Output('time_area', 'children'),
    Input('store', 'data')
)
def create_graph(data):
    df = data
    return df

if __name__ == ' __main__':
    app.run_server(debug=True)

```

schedule.py

```auto
import schedule
import time
import requests

def updateDF():
    r = requests.post('http://127.0.0.1:8050/updateDF', headers={'content-type': 'application/json'})
    print(r.content)

# Update DF internally
schedule.every(30).seconds.do(updateDF)

while True:
    schedule.run_pending()

```

Just start both and watch the df update in the app as the other pings it every 30 seconds.

* * *

This will fail on a deployed server with multiple workers as it will only update the one worker.

---

<div class="post-metadata">

**Author:** ![TemaTorg](https://avatars.discourse-cdn.com/v4/letter/t/4bbf92/32.png) [@TemaTorg](https://community.plotly.com/u/TemaTorg)\
**Post date:** [September 13, 2023, 7:13pm UTC](https://community.plotly.com/t/dcc-interval-doesnt-update-data/78479/16 "2023-09-13T19:13:57Z")

</div>

Great! Very intresting solution, thank you!

> [@jinnyzor](#):
>
> Just start both and watch the df update in the app as the other pings it every 30 seconds.

Yes, it works!

> [@jinnyzor](#):
>
> This will fail on a deployed server with multiple workers as it will only update the one worker.

How can this be fixed? Which worker exactly will change? I’ll test it tomorrow on deployed server.

---

<div class="post-metadata">

**Author:** ![jinnyzor](https://sea2.discourse-cdn.com/flex024/user_avatar/community.plotly.com/jinnyzor/32/21194_2.png) [@jinnyzor](https://community.plotly.com/u/jinnyzor)\
**Post date:** [September 13, 2023, 7:15pm UTC](https://community.plotly.com/t/dcc-interval-doesnt-update-data/78479/17 "2023-09-13T19:15:48Z")

</div>

If you only have 1 gunicorn worker, you dont need to worry, but if you have more, it will be whichever one receives the request. There is no way to make a request to each worker.

---

<div class="post-metadata">

**Author:** ![TemaTorg](https://avatars.discourse-cdn.com/v4/letter/t/4bbf92/32.png) [@TemaTorg](https://community.plotly.com/u/TemaTorg)\
**Post date:** [September 14, 2023, 10:49pm UTC](https://community.plotly.com/t/dcc-interval-doesnt-update-data/78479/18 "2023-09-14T22:49:33Z")

</div>

Today we tested app on deployed server and it worked perfect (2 clients)! Thank you 👍

Finally we did it using Threads:

```auto
from dash import Dash, html, Input, Output, dcc
import dash_bootstrap_components as dbc
from datetime import datetime
import json
import requests
import time
import schedule
import threading

DATA = datetime.now()

app = Dash( __name__ )
app.layout = dbc.Container([
    dbc.Row(
        html.Div(id='time_area', children=DATA)
    ),
    dbc.Row(
        dcc.DatePickerRange(id='picker_range')
    ),
    dcc.Interval(id='interval-component', interval=10*1000, n_intervals=0)
])

@app.server.route('/updateDF', methods=['POST'])
def updateDF():
    global DATA
    DATA = datetime.now()
    return json.dumps({'status': 'successful', 'data': str(DATA)})

@app.callback(
    Output('picker_range', 'end_date'),
    Input('interval-component', 'n_intervals')
)
def update_data(n):
    day = datetime.date(datetime.now())
    return day

@app.callback(
    Output('time_area', 'children'),
    Input('picker_range', 'end_date')
)
def create_graph(data):
    df = DATA
    return df

def update_request():
    r = requests.post('http://127.0.0.1:8050/updateDF', headers={'content-type': 'application/json'})
    print(r.content)

schedule.every().minutes.at(":15").do(update_request)

def sched():
    while True:
        schedule.run_pending()
        time.sleep(1)

thread = threading.Thread(target=sched)
thread.start()

if __name__ == ' __main__':
    app.run_server(debug=True)

```
