Extension servers are HTTP(S) endpoints that distribute shared macros, SQL modules, and proto descriptors to the Perfetto UI. They are the recommended way for teams and organizations to share reusable trace analysis workflows.
Without extension servers, sharing macros or SQL modules means copy-pasting JSON between teammates. This doesn‘t scale: definitions get out of date, new team members miss them, and there’s no single source of truth. Extension servers solve this by letting you host extensions in one place and have everyone load them automatically.
Extension servers are optional and never load-bearing. The Perfetto UI works fully without any servers configured — servers only provide optional enhancements.
All extensions are declarative and safe:
Macros loaded from extension servers appear in the command palette (Ctrl+Shift+P) alongside locally-defined macros. They show the server and module name as a source label so you can tell where each macro comes from.
See Commands and Macros for how macros work.
SQL modules become available for use in the query editor and in startup commands. Use them with:
INCLUDE PERFETTO MODULE <namespace>.<module_name>;
For example, if a server with namespace com.acme provides a module called com.acme.startup, you would write:
INCLUDE PERFETTO MODULE com.acme.startup;
See PerfettoSQL Getting Started for more on SQL modules.
Proto descriptors allow the UI to decode and display custom protobuf messages embedded in traces without needing the .proto files compiled into the UI. These are registered automatically when the extension server loads.
Each extension server hosts a manifest that declares:
com.acme)When the Perfetto UI starts, it fetches the manifest from each configured server, then loads extensions from the enabled modules. If a server is unreachable or returns errors, it is skipped — other servers and the rest of the UI are unaffected.
Extension servers organize content into modules. For example, a corporate server might offer:
default — General-purpose macros and SQL modulesandroid — Android-specific analysis workflowschrome — Chrome rendering performance toolsWhen you add a server, the default module is selected automatically. Other modules are opt-in.
All macro IDs and SQL module names from a server must start with the server's namespace (e.g., com.acme.). This prevents naming conflicts when multiple extension servers are configured. The UI enforces this and rejects extensions that violate the convention.
Extensions are loaded once at UI startup. If you change your extension server configuration (add/remove servers, change modules), you need to reload the page for changes to take effect.
Extension servers come in two types:
raw.githubusercontent.com (public repos) or the GitHub API (private repos). This is the easiest option — no server infrastructure needed.Each server type supports different authentication methods:
| Server type | Auth method | When to use |
|---|---|---|
| GitHub | None | Public repositories |
| GitHub | Personal Access Token | Private repositories |
| HTTPS | None | Publicly accessible servers |
| HTTPS | Basic Auth | Username/password protected servers |
| HTTPS | API Key | Bearer token, X-API-Key, or custom header |
| HTTPS | SSO | Corporate SSO with cookie-based authentication |
For most use cases (public GitHub repos + link sharing), no authentication is needed. See the protocol reference for the exact headers the UI sends for each auth type.
The easiest way to create an extension server is to use a GitHub repository — no custom server infrastructure needed.
Start by forking (or importing, for a private copy) the perfetto-test-extensions template repository on GitHub. This gives you a ready-made structure with a GitHub Action that automatically builds the endpoint files when you push.
Edit config.yaml to set your extension's name and namespace:
name: My Team Extensions namespace: com.example.myteam
The namespace must be unique to your organization and follows reverse-domain notation. All macro IDs and SQL module names must start with this namespace.
You can also configure which modules your server offers. By default, the template includes a default module. Add more if you want to organize extensions by team or topic:
name: My Team Extensions namespace: com.example.myteam modules: - id: default name: Default - id: android name: Android - id: chrome name: Chrome
Add .sql files under src/{module}/sql_modules/. The filename determines the SQL module name based on your namespace:
src/default/sql_modules/helpers.sql becomes INCLUDE PERFETTO MODULE com.example.myteam.helpers;src/default/sql_modules/foo/bar.sql becomes INCLUDE PERFETTO MODULE com.example.myteam.foo.bar;You can organize SQL files into subdirectories — each path component becomes a dot-separated part of the module name.
See PerfettoSQL Getting Started for how to write SQL modules.
Add .yaml or .json files under src/{module}/macros/. Each macro has an id, a display name, and a run list of commands.
YAML example (src/default/macros/show_long_tasks.yaml):
id: com.example.myteam.ShowLongTasks name: Show Long Tasks run: - id: dev.perfetto.RunQueryAndShowTab args: - "SELECT * FROM slice WHERE dur > 50000000"
Equivalent JSON (src/default/macros/show_long_tasks.json):
{ "id": "com.example.myteam.ShowLongTasks", "name": "Show Long Tasks", "run": [ { "id": "dev.perfetto.RunQueryAndShowTab", "args": ["SELECT * FROM slice WHERE dur > 50000000"] } ] }
Macro IDs must start with your namespace (e.g., com.example.myteam.). See the Commands Automation Reference for the full list of available commands to use in macros.
Push your changes to main. The included GitHub Action builds the generated endpoint files (manifest, modules/*/macros, etc.) and commits them automatically.
owner/repo format (e.g., my-org/perfetto-extensions).main).default module is selected automatically; enable others as needed.For private repositories, select Personal Access Token (PAT) under authentication:
https://perfetto-ext.corp.example.com). The https:// prefix is added automatically if omitted.Click the Share button on any server in Settings to copy a shareable URL. When someone opens the link:
Secrets (PATs, passwords, API keys) are automatically stripped from shared URLs. Recipients enter their own credentials if the server requires authentication.
In the Extension Servers settings section, use the action buttons to:
Changes require a page reload to take effect.
If you need more control than a GitHub repository provides — dynamic content, corporate SSO, or integration with internal systems — you can host an extension server on any HTTPS endpoint.
An extension server is a set of JSON endpoints. At minimum you need:
https://your-server.example.com/manifest → server metadata https://your-server.example.com/modules/default/macros → macros (optional) https://your-server.example.com/modules/default/sql_modules → SQL modules (optional)
You can serve these as static files (nginx, GCS, S3) or from a dynamic server (Flask, Express, etc.). The server must set CORS headers to allow the Perfetto UI to make cross-origin requests.
See the Extension Server Protocol Reference for the full endpoint specification, JSON schemas, CORS requirements, and examples including a minimal Python/Flask server.
If extensions fail to load, the UI shows an error dialog listing what went wrong. Errors are non-blocking — the UI works normally and extensions from other servers that loaded successfully remain available.
Below are the error messages you may see and how to fix them.
The UI could not reach the server at all. This is usually a network or CORS issue.
F12) and look for “CORS policy” errors. See the CORS requirements for what headers to set. GitHub-hosted servers don’t need CORS configuration.http:// URLs. Use https:// for your server.The server was reachable but returned an HTTP error.
The server returned a response that isn't valid JSON.
Content-Type: application/json and valid JSON. If using the GitHub template, make sure the GitHub Action has run successfully after your last push — check the Actions tab in your repository.The server returned valid JSON but it doesn't match the expected schema.
name, namespace, features, modules in the manifest) or using the wrong field names.You have a module enabled in settings that the server‘s manifest doesn’t list.
A macro‘s id field doesn’t match the server's namespace.
MyMacro to com.acme.MyMacro). See namespace enforcement.Same as above, but for SQL modules. The module‘s name field must start with the server’s namespace.