# Astro page layout and middleware execution order

> Understand the order pages, layouts, and middleware run in Astro: page code runs when you call next(), but layout code runs after the middleware finishes.

Author: [Flavio Copes](https://flaviocopes.com/about/) | Published: 2024-03-15 | Topics: [Astro](https://flaviocopes.com/tags/astro/) | Canonical: https://flaviocopes.com/astro-page-layout-and-middleware-execution-order/

One thing I discovered the hard way (through trial and error) is the order in which pages, layouts and the middleware are called in [Astro](https://flaviocopes.com/astro-introduction/).

I was doing something related to caching, and I had a workflow where I was doing something in a page, like setting a response header property, or setting a value in `Astro.locals` :

```javascript
---
Astro.locals.test = 'test'
Astro.response.headers.set('test', 'test')
---

<p>test</p>
```

After doing so, I had access to those values after calling `next()` in the middleware:

```javascript
import type { MiddlewareHandler } from 'astro'

export const onRequest: MiddlewareHandler = async (context, next) => {

	const response = await next()
	
	console.log(context.locals.test)
	console.log(response.headers.get('test'))

	return response
}
```

Then I decided to move some of the logic I had in the page in a layout, because I was duplicating some portion of code across multiple pages:

```javascript
---
import Layout from '@layouts/Layout.astro'
---

<Layout />
```

In this layout I did the exact same thing I had in the page, previously:

```javascript
---
Astro.locals.test = 'test'
Astro.response.headers.set('test', 'test')
---

<p>test</p>
```

but to my surprise, none of those values were now available in the middleware.

Turns out that (to my understanding) the order of execution is different.

The page code is ran calling `next()` in the middleware.

The layout code is ran after the middleware runs.

To fix my problem I eventually moved some of the logic I had in the middleware to my layout.
