---
title: Python on the Compute platform
summary: null
url: https://www.fastly.com/documentation/guides/compute/developer-guides/python
---

The Compute platform supports application code written in [Python](https://www.python.org/), a popular, readable language with a large ecosystem of libraries. The Python SDK builds your Python application into a [WebAssembly (Wasm)](https://webassembly.org/) component that runs on the Compute platform.

> **IMPORTANT:** 
>
> This information is part of a beta release. For additional details, read our [product and feature lifecycle](https://docs.fastly.com/products/fastly-product-lifecycle#beta) descriptions.
>
>

## Quick access

- [SDK reference](https://github.com/fastly/compute-sdk-python)
- [Starter kits](/solutions/starters/python/)
- [Examples](https://github.com/fastly/compute-sdk-python/tree/main/examples)

## Python language support

The Compute platform's Python SDK requires Python 3.12 or later. The SDK is distributed as the [`fastly-compute`](https://pypi.org/project/fastly-compute/) package and installs the `fastly-compute-py` build tool used to produce a Wasm component from your Python code.

Because the build process compiles your application to WebAssembly, some Python features are not yet available on the platform. In particular, third-party 'native code' extension modules are not currently supported. See [Caveats](https://www.fastly.com/documentation/guides/compute/developer-guides/python#caveats) for the full list.

## Project layout

If you don't yet have a working toolchain and Compute service set up, start by [getting set up](https://www.fastly.com/documentation/guides/compute/getting-started-with-compute/).

To work with the Python SDK, you need two system dependencies installed:

1. The [Fastly CLI](https://www.fastly.com/documentation/reference/tools/cli/), version 15.5.0 or later. Earlier versions don't recognize Python as a Compute language.
2. The [`uv`](https://docs.astral.sh/uv/getting-started/installation/) Python package manager, version 0.5.0 or later.

`uv` installs and manages the Python SDK and build tooling in an isolated environment, so you don't need to install those globally.

To create a project, run <kbd>fastly compute init</kbd> in an empty directory and choose Python when prompted for a language, then select a [starter kit](https://www.fastly.com/documentation/solutions/starters/python/):

```term
$ mkdir my-compute-service
$ cd my-compute-service
$ fastly compute init
```

The CLI generates the `fastly.toml` metadata file and the project files from the starter kit you chose. The current working directory will contain a file tree resembling the following:

```plain lineNumbers=false nocopy
├── .gitignore
├── README.md
├── fastly.toml
├── main.py
├── pyproject.toml
└── welcome-to-compute.html
```

The most 

- Python project metadata: `pyproject.toml` describes the dependencies of your project, managed using [`uv`](https://docs.astral.sh/uv/). Running a build also creates a `uv.lock` file that pins the resolved versions. Add further dependencies with <kbd>uv add</kbd>, for example <kbd>uv add flask</kbd>.
- Fastly metadata: The `fastly.toml` file contains metadata required by Fastly to deploy your package to a Fastly service. It is generated by the <kbd>fastly compute init</kbd> command. [Learn more about `fastly.toml`](https://www.fastly.com/documentation/reference/compute/fastly-toml/).

## Building and deploying

Use <kbd>fastly compute build</kbd> to build a Wasm component from your project, <kbd>fastly compute serve</kbd> to test your service locally, and <kbd>fastly compute deploy</kbd> to deploy it to Fastly.

The CLI builds Python projects by running `uv run fastly-compute-py build` for you, so you don't need to set the `scripts.build` property in `fastly.toml`. To customize the build, set it explicitly:

```toml
[scripts]
build = "uv run fastly-compute-py build"
```

The `fastly-compute-py` build tool determines which module contains your service from the `[tool.fastly-compute]` section of your `pyproject.toml`. Starter kits set this for you, pointing `entry` at your module (without the `.py` extension):

```toml
[tool.fastly-compute]
entry = "main"
```

[Learn more about `fastly.toml`](https://www.fastly.com/documentation/reference/compute/fastly-toml/).

## Main interface

The most common way to build a Compute program in Python is to write a standard [WSGI](https://peps.python.org/pep-3333/) application and wrap it with `WsgiHttpIncoming`. This lets you use familiar web frameworks such as Flask or Bottle:

```python
from flask import Flask
from fastly_compute.wsgi import WsgiHttpIncoming

app = Flask(__name__)

@app.route("/")
def index():
    return "Hello from Python on Fastly Compute!"

HttpIncoming = WsgiHttpIncoming(app)
```

`WsgiHttpIncoming` adapts your WSGI application to Fastly's incoming request handler. The module assigned to `HttpIncoming` is invoked for each request that Fastly receives for a domain attached to your service, and it must produce a response that can be served to the client.

> **HINT:** All packages needed at runtime must be imported when your entry point module is imported, so that the SDK's memory-snapshotting build process can retain them. Avoid deferred (non-top-level) imports in code that runs at request time. Refer to [Caveats](https://www.fastly.com/documentation/guides/compute/developer-guides/python#caveats) for more information.

You can also write directly against Fastly's API instead of using a WSGI framework, which is useful for services that don't fit the request/response model of a web framework.

{/_ TODO(DEVLIB-2225): Document the non-WSGI "raw" handler interface (the object/callable assigned to HttpIncoming without WsgiHttpIncoming) once a supported, stable public API and example are available. The SDK README notes this is supported but does not show a canonical example. _/}

## Communicating with backend servers and the Fastly cache

Requests to a [backend](https://www.fastly.com/documentation/guides/integrations/non-fastly-services/developer-guide-backends) defined on your service are made using the `fastly_compute.requests` module, which provides a familiar [`requests`](https://requests.readthedocs.io/)-compatible HTTP client. If you specify a backend hostname as part of completing the <kbd>fastly compute deploy</kbd> wizard, it will be named the same as the hostname or IP address, but with `.` replaced with `_` (e.g., `151_101_129_57`).

Use the `fastly_backend` keyword argument to send a request to a named backend:

```python
import fastly_compute.requests as requests

BACKEND_NAME = "my_backend_name"

response = requests.get("https://example.com/api/getFlags", fastly_backend=BACKEND_NAME)
```

Requests forwarded to a backend will typically transit the Fastly cache, and the response may come from cache. For more precise or explicit control over the Fastly edge cache, refer to [Caching content with Fastly](https://www.fastly.com/documentation/guides/concepts/cache).

The Python SDK also supports [dynamic backends](https://www.fastly.com/documentation/guides/integrations/non-fastly-services/developer-guide-backends#dynamic-backends). If you make a request to a full URL without specifying a `fastly_backend`, a backend for that origin is created dynamically at runtime:

```python
import fastly_compute.requests as requests

# Uses a dynamically created backend for the request's origin
response = requests.get("https://http-me.fastly.dev/get")
```

Fastly-specific timeouts can be configured with `TimeoutConfig`:

```python
import fastly_compute.requests as requests
from fastly_compute.requests import TimeoutConfig

timeout_config = TimeoutConfig(
    connect=5.0,       # 5s to establish a connection
    first_byte=30.0,   # 30s to receive the first byte
    between_bytes=2.0  # 2s max between bytes
)

response = requests.get(
    "https://api.example.com/data",
    fastly_backend="api-backend",
    fastly_timeout=timeout_config,
)
```

### Compression

Fastly can compress and decompress content automatically, and it is often easier to use these features than to try to perform compression or decompression within your Python code. Learn more about [compression with Fastly](https://www.fastly.com/documentation/guides/concepts/compression).

## Composing requests and responses

In addition to forwarding requests to backends, you can construct requests and read structured responses using the `fastly_compute.requests` module. This is useful if you want to make an arbitrary API call that is not derived from the client request. The response object exposes the same attributes you'd expect from the `requests` library, such as `status_code`, `headers`, `text`, `content`, and `ok`, along with helpers like `json()`:

```python
import fastly_compute.requests as requests

response = requests.post(
    "https://http-me.fastly.dev/post",
    json={"key": "value"},
)

if response.ok:
    data = response.json()
```

When you build your service on a WSGI framework, you construct responses to the client using that framework's own primitives (for example, returning a string, tuple, or response object from a Flask view). Refer to your framework's documentation for details.

## Parsing and transforming responses

Reading a backend response's body into memory (for example, via `response.text` or `response.content`) will consume the entire body into memory. This can be appropriate where a response is known to be small or needs to be complete to be parsable, such as when parsing JSON. For large payloads, prefer to stream the response through your service rather than buffering it in full.

This example reads a backend response and replaces every occurrence of "cat" with "dog" before returning it:

```python
import fastly_compute.requests as requests
from flask import Flask, Response
from fastly_compute.wsgi import WsgiHttpIncoming

app = Flask(__name__)

@app.route("/")
def transform():
    backend_response = requests.get(
        "https://http-me.fastly.dev/get",
        fastly_backend="my_backend_name",
    )
    body = backend_response.text.replace("cat", "dog")
    return Response(body, status=backend_response.status_code)

HttpIncoming = WsgiHttpIncoming(app)
```

## Using edge data

Fastly allows you to configure various forms of data stores for your services, both for dynamic configuration and for storing data at the edge. The Python SDK exposes the [`config_store`](https://github.com/fastly/compute-sdk-python/blob/main/fastly_compute/config_store.py) module for read-only access to [config stores](https://www.fastly.com/documentation/guides/compute/edge-data-storage/working-with-config-stores/):

```python
from fastly_compute.config_store import ConfigStore

with ConfigStore.open("my-config") as config:
    api_url = config.get("api_url", "https://api.example.com")
```

All edge data resources are account-level, [service-linked resources](https://www.fastly.com/documentation/guides/compute/edge-data-storage/about-edge-data-stores/), allowing a single store to be accessed from multiple Fastly services.

{/_ TODO(DEVLIB-2226): Document KV store and secret store access for Python once those modules are available in the fastly-compute package. At time of writing only `config_store` is exposed. _/}

## Logging

The `fastly_compute.log` module provides an interface for sending logs to [Fastly real-time logging](https://www.fastly.com/documentation/guides/integrations/non-fastly-services/developer-guide-logging/), which can be attached to many third-party logging providers. Before adding logging code to your Compute program, set up your log endpoint using the CLI, API, or web interface. Log endpoints are referenced in your code by name.

You can write to an endpoint directly:

```python
from fastly_compute.log import LogEndpoint

endpoint = LogEndpoint.open("my_logs")
endpoint.write("Hello from Fastly Compute!")
```

The SDK also provides `FastlyLogHandler`, so you can route Python's standard [`logging`](https://docs.python.org/3/library/logging.html) module to a Fastly endpoint:

```python
import logging
from fastly_compute.log import FastlyLogHandler

logger = logging.getLogger("my_app")
logger.setLevel(logging.INFO)
logger.addHandler(FastlyLogHandler("my_logs"))

logger.info("Request processed")
```

## Using dependencies

The Compute build process compiles your code to WebAssembly, so it supports pure Python dependencies. Add packages to your project with `uv add`, and they'll be managed in your `pyproject.toml` and `uv.lock`. WSGI web frameworks such as [Flask](https://flask.palletsprojects.com/) and [Bottle](https://bottlepy.org/) are known to work.

Third-party 'native code' extension modules are not currently supported. All packages needed at runtime must be imported when your entry point module is imported, so avoid deferred (non-top-level) imports in code that runs at request time.

## Testing and debugging

Logging is the main mechanism to debug Compute programs. Log output from live services can be monitored via live log tailing. The local test server displays all log output automatically. Refer to [Testing & debugging](https://www.fastly.com/documentation/guides/compute/developer-guides/testing) for more information about choosing an environment in which to test your program.

You can run your service locally with <kbd>fastly compute serve</kbd>, which builds and serves your project so you can exercise it with real requests before deploying.

## Caveats

The Python SDK is available as part of Fastly's [Beta program](https://docs.fastly.com/products/fastly-product-lifecycle#beta), and there are some limitations to be aware of:

- Its in-Python API may change in backward-incompatible ways during the beta period.
- Third-party 'native code' extension modules are not yet supported.
- All packages needed at runtime must be imported when your entry point module is imported, so that the SDK's memory-snapshotting build process can retain them. This can happen transitively, but beware of deferred imports (such as non-top-level imports); if they aren't triggered by importing your entry point, they will fail at runtime. If you use third-party code that relies on non-top-level imports, you can ensure it works by importing it at the top level in your own code.
