Extension Servers

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.

Why extension servers?

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.

Key properties

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 are sequences of UI commands — no JavaScript execution.
  • SQL modules run inside trace processor's existing sandbox.
  • Proto descriptors are binary type definitions (data only).

What extension servers provide

Macros

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

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

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.

How extension servers work

Each extension server hosts a manifest that declares:

  • The server's name and namespace (e.g., com.acme)
  • Which features it supports (macros, SQL modules, proto descriptors)
  • Which modules are available (named collections of extensions)

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.

Modules

Extension servers organize content into modules. For example, a corporate server might offer:

  • default — General-purpose macros and SQL modules
  • android — Android-specific analysis workflows
  • chrome — Chrome rendering performance tools

When you add a server, the default module is selected automatically. Other modules are opt-in.

Namespacing

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.

Lifecycle

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.

Server types and authentication

Extension servers come in two types:

  • GitHub — Extensions hosted in a GitHub repository. The UI fetches files directly from raw.githubusercontent.com (public repos) or the GitHub API (private repos). This is the easiest option — no server infrastructure needed.
  • HTTPS — Extensions hosted on any HTTPS endpoint: a static file host (GCS, S3, nginx), a dynamic server (Flask, Express), or corporate infrastructure. The server must set CORS headers to allow the Perfetto UI to fetch from it.

Each server type supports different authentication methods:

Server typeAuth methodWhen to use
GitHubNonePublic repositories
GitHubPersonal Access TokenPrivate repositories
HTTPSNonePublicly accessible servers
HTTPSBasic AuthUsername/password protected servers
HTTPSAPI KeyBearer token, X-API-Key, or custom header
HTTPSSSOCorporate 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.

Creating extensions with GitHub

The easiest way to create an extension server is to use a GitHub repository — no custom server infrastructure needed.

Fork the template repository

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.

Configure your server

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 modules

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 macros

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 and deploy

Push your changes to main. The included GitHub Action builds the generated endpoint files (manifest, modules/*/macros, etc.) and commits them automatically.

Adding an extension server in the Perfetto UI

Add a GitHub server

  1. Go to Settings (gear icon in the sidebar) and scroll to Extension Servers, or open the settings directly.
  2. Click Add Server and select GitHub.
  3. Enter the repository in owner/repo format (e.g., my-org/perfetto-extensions).
  4. Enter the branch or tag in the Ref field (e.g., main).
  5. The UI fetches the manifest and shows available modules. The default module is selected automatically; enable others as needed.
  6. Click Save and reload the page.

For private repositories, select Personal Access Token (PAT) under authentication:

  1. Go to GitHub personal access tokens and click Generate new token.
  2. Under Repository access, select Only select repositories and choose your extension repo.
  3. Under Permissions > Repository permissions, set Contents to Read-only.
  4. Generate the token and enter it in the Perfetto UI when adding the server.

Add an HTTPS server

  1. Click Add Server and select HTTPS.
  2. Enter the server URL (e.g., https://perfetto-ext.corp.example.com). The https:// prefix is added automatically if omitted.
  3. Select modules and configure authentication (see below).
  4. Click Save and reload the page.

Sharing extension servers

Click the Share button on any server in Settings to copy a shareable URL. When someone opens the link:

  • If they don't have the server configured, the Add Server dialog opens pre-populated with the shared configuration.
  • If they already have the server, the Edit dialog opens with the shared modules merged in.

Secrets (PATs, passwords, API keys) are automatically stripped from shared URLs. Recipients enter their own credentials if the server requires authentication.

Managing servers

In the Extension Servers settings section, use the action buttons to:

  • Toggle — Enable or disable a server without removing it.
  • Edit — Change modules, authentication, or other settings.
  • Share — Copy a shareable URL to the clipboard.
  • Delete — Remove the server.

Changes require a page reload to take effect.

Creating an HTTPS extension server

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.

Troubleshooting

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.

“Failed to fetch <url>: <error>”

The UI could not reach the server at all. This is usually a network or CORS issue.

  • Check the URL. Open the URL in a new browser tab. If you can't reach it, the server may be down, the URL may be wrong, or you may need to be on a VPN.
  • Check CORS headers. If the URL loads in a tab but the UI shows a fetch error, the server likely isn‘t setting CORS headers. Open the browser console (F12) and look for “CORS policy” errors. See the CORS requirements for what headers to set. GitHub-hosted servers don’t need CORS configuration.
  • Check for mixed content. The Perfetto UI is served over HTTPS, so it cannot fetch from http:// URLs. Use https:// for your server.

“Fetch failed: <url> returned <status>”

The server was reachable but returned an HTTP error.

  • 401 or 403 — Authentication failed. For GitHub PATs, check that the token hasn't expired and has read access to the repository (Settings > Personal access tokens). For HTTPS servers with SSO, try logging into the server directly in a new tab to refresh your session, then reload the Perfetto UI.
  • 404 — The endpoint doesn't exist. Check that the server implements the expected endpoint paths and that the repository/branch/path are correct.

“Failed to parse JSON from <url>: <error>”

The server returned a response that isn't valid JSON.

  • Check that the endpoint returns 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.

“Invalid response from <url>: <error>”

The server returned valid JSON but it doesn't match the expected schema.

  • Compare your response against the expected format in the protocol reference. Common mistakes include missing required fields (name, namespace, features, modules in the manifest) or using the wrong field names.

“Module ‘<name>’ not found on server”

You have a module enabled in settings that the server‘s manifest doesn’t list.

  • Edit the server in Settings and check which modules are enabled. If a module was renamed or removed from the server, deselect it and save.

“Macro ID ‘<id>’ must start with namespace ‘<ns>.’”

A macro‘s id field doesn’t match the server's namespace.

  • If you maintain the server: update the macro ID to start with your namespace (e.g., change MyMacro to com.acme.MyMacro). See namespace enforcement.
  • If you don't maintain the server: contact the server maintainer.

“SQL module name ‘<name>’ must start with namespace ‘<ns>.’”

Same as above, but for SQL modules. The module‘s name field must start with the server’s namespace.

See also