Uptrace Configuration Reference

All Uptrace settings live in a single YAML file. This page covers the main options for databases, networking, authentication, processing pipelines, and features. Run uptrace config create to get the full default file.

Configuration file

Creating the config file

Generate a default configuration file:

shell
./uptrace --config=/path/to/config.yml config create

The command writes a random service.secret into a new file that only its owner can read (mode 0600), and it does not overwrite an existing file.

If you write the config by hand, set service.secret to a random value, for example from openssl rand -hex 32. Outside service.env: dev, Uptrace refuses an empty secret and the FIXME placeholder: uptrace serve and uptrace config validate exit with service.secret is the shipped placeholder.

Specify the config file location using either method:

shell
# CLI argument (recommended)
uptrace --config=/etc/uptrace/config.yml serve

# Environment variable
export UPTRACE_CONFIG=/etc/uptrace/config.yml
uptrace serve

If no path is specified, Uptrace defaults to /etc/uptrace/config.yml.

Environment variables

Use environment variables in your YAML configuration for secrets and per-environment overrides:

yml
pg:
  addr: ${UPTRACE_PG_ADDR:localhost:5432}
  user: ${UPTRACE_PG_USER:uptrace}
  password: ${UPTRACE_PG_PASSWORD}
  database: ${UPTRACE_PG_DATABASE:uptrace}
SyntaxBehavior
${ENV_VAR_NAME}Simple substitution
${ENV_VAR_NAME:default_value}Substitution with fallback
$$Literal $

Variables are expanded using Go's os.Expand before YAML parsing.

File layout

Each top-level key is one subsystem or one dependency, for example pg, ch_cluster, listen, auth, or mailer. Two sections group related blocks:

SectionHolds
pipelinesOne block for each data pipeline: spans, span_links, logs, events, metrics, profiling, service_graph, project_metrics, query_usages
alertingThe alerting switches, the monitor kinds (metric_monitors, error_monitors), the alert_trends schedule, and incidents

The OAuth apps live under auth.github and auth.google, and the per-trace overrides under trace.overrides.

Older releases used other keys for some options, for example a top-level spans block instead of pipelines.spans. The old keys still work: Uptrace logs a deprecation warning for each one on startup. Run uptrace config fix to rewrite them.

Fixing deprecated options

uptrace config fix rewrites the deprecated options of the config file to their current keys. Without --write, it prints each fix and a diff, and changes nothing:

shell
uptrace --config=/etc/uptrace/config.yml config fix
text
spans -> pipelines.spans
metric_monitors -> alerting.metric_monitors
github_oauth -> auth.github
auth.sign_up_disabled -> auth.sign_up

--- /etc/uptrace/config.yml
+++ /etc/uptrace/config.yml (fixed)
@@ -1,12 +1,14 @@
 auth:
-  sign_up_disabled: true
+  sign_up: false
 
-github_oauth:
-  client_id: ${GITHUB_CLIENT_ID}
-  client_secret: ${GITHUB_CLIENT_SECRET}
+  github:
+    client_id: ${GITHUB_CLIENT_ID}
+    client_secret: ${GITHUB_CLIENT_SECRET}
 
-spans:
-  max_threads: 16 # Processing goroutines
+pipelines:
+  spans:
+    max_threads: 16 # Processing goroutines
 
-metric_monitors:
-  max_workers: 8
+alerting:
+  metric_monitors:
+    max_workers: 8

run with --write to apply

The command exits with status 1 when the file has a deprecated option and 0 when it has none, so you can use it as a check in CI or before an upgrade.

To apply the fixes, add --write. Uptrace keeps the original file as config.yml.bak:

shell
uptrace --config=/etc/uptrace/config.yml config fix --write
text
spans -> pipelines.spans
metric_monitors -> alerting.metric_monitors
github_oauth -> auth.github
auth.sign_up_disabled -> auth.sign_up
wrote /etc/uptrace/config.yml (the original is /etc/uptrace/config.yml.bak)

How the rewrite works:

  • It changes only the lines of deprecated options. Comments, key order, formatting, and ${VAR} references stay as they are. Commented-out examples are not changed.
  • It deletes an option that the current release no longer uses, for example ch_schema.spans_index.ttl_delete of v2.0, and prints <option>: removed, it is no longer used. Until you delete it, Uptrace accepts such an option and logs a warning. An option inside a one-line { ... } table stays in place with a note to edit it by hand.
  • Before it writes, it checks that the new file gives exactly the same configuration and has no deprecated option left. If the check fails, it writes nothing.
  • An option whose value is an environment reference that must be inverted or converted, such as sign_up_disabled: ${SIGN_UP_OFF}, stays in place with a note to edit it by hand. The command then still exits with status 1.
  • Like uptrace config validate, it does not connect to any database.

Database configuration

Uptrace uses PostgreSQL for metadata (users, projects, dashboards, alerts) and ClickHouse for high-volume telemetry (spans, logs, metrics).

PostgreSQL

PostgreSQL stores application metadata. This database typically requires only a few megabytes of storage.

yml
pg:
  addr: localhost:5432
  user: uptrace
  password: uptrace
  database: uptrace

  #tls:
  #  insecure_skip_verify: true  # Only for self-signed certificates

With read replicas:

yml
pg:
  addr: primary-host:5432
  user: uptrace
  password: uptrace
  database: uptrace

  read_replicas:
    - addr: standby-host1:5432
      role: read     # serves reads in rotation with the primary
    - addr: standby-host2:5432
      role: standby  # takes reads only while nothing else is healthy

Using a connection string:

yaml
pg:
  dsn: postgresql://user:password@host:5432/database?sslmode=verify-full

ClickHouse

ClickHouse stores telemetry data — spans, logs, and metrics. It's optimized for analytical queries and time-series data.

yml
ch_cluster:
  cluster: 'uptrace1'
  replicated: false   # Enable for automatic failover
  distributed: false  # Enable for horizontal scaling (Premium only)

  shards:
    - replicas:
        - addr: localhost:9000
          user: default
          password: ''
          database: uptrace
          dial_timeout: 3s
          write_timeout: 5s
          max_retries: 3
          max_execution_time: 15s

With replication (3 nodes):

yml
ch_cluster:
  cluster: 'uptrace1'
  replicated: true

  shards:
    - replicas:
        - addr: clickhouse-1:9000
          user: default
          password: ''
          database: uptrace

        - addr: clickhouse-2:9000
          user: default
          password: ''
          database: uptrace

        - addr: clickhouse-3:9000
          user: default
          password: ''
          database: uptrace

Using a connection string:

yaml
ch_cluster:
  shards:
    - replicas:
        - dsn: clickhouse://your_username:your_password@your_host:9000/your_database
          dial_timeout: 3s
          write_timeout: 5s
          max_retries: 3
          max_execution_time: 15s

Advanced ClickHouse settings

Query settings:

yml
ch_cluster:
  shards:
    - replicas:
        - addr: localhost:9000
          query_settings:
            async_insert: 1
            wait_for_async_insert: 1
            max_memory_usage: 10000000000 # 10 GB per query

TLS — ClickHouse server side:

xml
<?xml version="1.0" ?>
<clickhouse>
  <tcp_port_secure>9440</tcp_port_secure>

  <openSSL>
    <server>
      <certificateFile>/etc/clickhouse/certs/chnode.crt</certificateFile>
      <privateKeyFile>/etc/clickhouse/certs/chnode.key</privateKeyFile>
      <verificationMode>relaxed</verificationMode>
      <caConfig>/etc/clickhouse/certs/Uptrace_CA.crt</caConfig>
      <cacheSessions>true</cacheSessions>
      <disableProtocols>sslv2,sslv3</disableProtocols>
      <preferServerCiphers>true</preferServerCiphers>
    </server>
  </openSSL>
</clickhouse>

TLS — Uptrace side:

yml
ch_cluster:
  shards:
    - replicas:
        - addr: localhost:9440
          user: default
          database: uptrace

          tls:
            ca_file: /etc/clickhouse/certs/Uptrace_CA.crt
            cert_file: /etc/clickhouse/certs/chnode.crt
            key_file: /etc/clickhouse/certs/chnode.key
            insecure_skip_verify: false

ClickHouse Cloud:

yml
ch_cluster:
  shards:
    - replicas:
        - addr: tm849a32za.us-central1.gcp.clickhouse.cloud:9440
          user: default
          password: your_cloud_password
          database: uptrace
          tls:
            server_name_override: 'tm849a32za.us-central1.gcp.clickhouse.cloud'

Database management

Resetting ClickHouse

Reset the ClickHouse database to apply schema changes or start fresh:

shell
uptrace migrate reset --database ch
uptrace migrate up

reset drops the ClickHouse database and creates it again, empty. up then creates the ClickHouse tables again. PostgreSQL is not changed.

Warning: This deletes all telemetry data (spans, logs, metrics).

Resetting PostgreSQL

Reset the PostgreSQL database to clear metadata:

shell
uptrace migrate reset --database pg
uptrace migrate up
uptrace db seed

reset drops the PostgreSQL database and creates it again, empty. up creates the PostgreSQL tables again, and db seed creates the projects and users of your config. The ClickHouse data stays.

Warning: This deletes all metadata including users, projects, dashboards, and alerts.

To reset both databases at once, run uptrace migrate reset without --database.

Emptying the databases

Delete all data and keep the schema:

shell
# Both databases
uptrace migrate truncate

# Only ClickHouse
uptrace migrate truncate --database ch

truncate keeps the tables and the migration records, so you do not need to run migrate up after it.

Schema configuration

Customize ClickHouse schema settings for performance and storage efficiency. Schema changes require a ClickHouse reset (uptrace migrate reset --database ch, then uptrace migrate up) and delete all existing data.

Storage and compression

yml
ch_schema:
  # LZ4: fast, moderate ratio. ZSTD(1): better ratio, slightly slower.
  compression: ZSTD(1)

  # Storage policies — map tables to storage tiers (SSD, HDD, S3)
  spans_index: { storage_policy: hot_storage }
  spans_data: { storage_policy: warm_storage }
  span_links: { storage_policy: cold_storage }
  logs_index: { storage_policy: hot_storage }
  logs_data: { storage_policy: warm_storage }
  events_index: { storage_policy: hot_storage }
  events_data: { storage_policy: warm_storage }
  timeseries: { storage_policy: hot_storage }
  datapoints: { storage_policy: hot_storage }

Replication setup

Step 1: Configure the ClickHouse cluster with at least 3 replicas. Set internal_replication = true to prevent data duplication.

xml
<clickhouse>
  <remote_servers>
    <uptrace1>
      <shard>
        <internal_replication>true</internal_replication>
        <replica>
          <host>clickhouse-1</host>
          <port>9000</port>
        </replica>
        <replica>
          <host>clickhouse-2</host>
          <port>9000</port>
        </replica>
        <replica>
          <host>clickhouse-3</host>
          <port>9000</port>
        </replica>
      </shard>
    </uptrace1>
  </remote_servers>
</clickhouse>

Step 2: Enable replication in Uptrace:

yml
ch_cluster:
  cluster: 'uptrace1'
  replicated: true

  shards:
    - replicas:
        - addr: clickhouse-1:9000
        - addr: clickhouse-2:9000
        - addr: clickhouse-3:9000

Step 3: Apply with uptrace migrate reset --database ch, then uptrace migrate up.

Step 4: Verify replication status:

sql
SELECT
    database,
    table,
    is_leader,
    replica_is_active
FROM system.replicas;

Expected output:

text
┌─database─┬─table───────────┬─is_leader─┬─replica_is_active────────────────────────┐
│ uptrace  │ spans_data      │         1 │ {'replica1':1,'replica2':1,'replica3':1} │
│ uptrace  │ spans_index     │         1 │ {'replica1':1,'replica2':1,'replica3':1} │
└──────────┴─────────────────┴───────────┴──────────────────────────────────────────┘

Network configuration

Ports

yml
listen:
  http:
    addr: ':80'    # OTLP/HTTP, REST API, web UI

  grpc:
    addr: ':4317'  # OTLP/gRPC

  #tls:
  #  cert_file: /etc/uptrace/uptrace.crt
  #  key_file: /etc/uptrace/uptrace.key

gRPC transport and stream lifetime

The gRPC listener accepts OTLP and OTel Arrow telemetry. These transport options rarely need tuning, but are available under listen.grpc:

yml
listen:
  grpc:
    addr: ':4317'

    # Largest message the server accepts (default: 64MiB).
    max_recv_msg_size: 67108864

    # Per-connection read/write buffers (defaults: 64KiB / 16KiB).
    read_buffer_size: 65536
    write_buffer_size: 16384

    # Reuse write buffers across connections to lower heap pressure (default: true).
    shared_write_buffer: true

    # Close each connection once it reaches this age, forcing OTel Arrow
    # streams to rotate so load balancers can redistribute clients evenly
    # (default: 5m).
    max_connection_age: 5m
OptionDefaultDescription
max_recv_msg_size64MiBMaximum message size the server accepts
read_buffer_size64KiBPer-connection read buffer
write_buffer_size16KiBPer-connection write buffer
shared_write_buffertrueReuse write buffers across connections
max_connection_age5mAge at which a connection is closed, bounding OTel Arrow stream lifetime

max_connection_age is the server-side bound on how long an OTel Arrow stream can live. After a connection reaches this age the server sends a gRPC GOAWAY and, following a one-minute grace period for in-flight requests, closes it. This recycles long-lived Arrow streams so an L4/L7 load balancer can rebalance clients across Uptrace instances and so dictionary state stays bounded. See the OTel Arrow in production experiment for the rationale.

When sending data with the OTel Arrow exporter, keep the client's arrow.max_stream_lifetime below this value so streams recycle gracefully — see Ingesting telemetry using OTel Arrow.

Domain and URL

yml
site:
  # Used for dashboard links, CORS, and auth redirects.
  # Must match your reverse proxy setup.
  url: https://uptrace.mycompany.com

  # Optional: dedicated ingestion endpoint.
  # Defaults to site.url if not set.
  ingest_url: https://ingest.mycompany.com

TLS configuration

Automatic TLS with Let's Encrypt

yml
certmagic:
  enabled: true
  staging_ca: false           # Set true for testing
  http_challenge_addr: ':80'  # Port for HTTP-01 challenge

Manual TLS certificates

Generate a self-signed certificate for development:

shell
openssl req -x509 -newkey rsa:4096 -sha256 -days 3650 -nodes \
  -keyout uptrace.key -out uptrace.crt -subj "/CN=localhost" \
  -addext "subjectAltName=DNS:localhost,DNS:uptrace.local"

Add to the system trust store:

shell
sudo cp uptrace.crt /usr/local/share/ca-certificates/
sudo update-ca-certificates

Configure Uptrace:

yml
listen:
  grpc:
    addr: ':4317'
  http:
    addr: ':443'
  tls:
    cert_file: /etc/uptrace/tls/uptrace.crt
    key_file: /etc/uptrace/tls/uptrace.key
    min_version: '1.2'

site:
  url: 'https://uptrace.mycompany.com'

Database TLS

Full TLS client options (PostgreSQL example):

yml
pg:
  addr: localhost:5432
  user: uptrace
  password: uptrace
  database: uptrace
  tls:
    cert_file: /etc/uptrace/client.crt
    key_file: /etc/uptrace/client.key
    ca_file: /etc/uptrace/ca.crt
    min_version: '1.2'
    max_version: '1.3'
    insecure_skip_verify: false
    server_name_override: ''

Common shortcuts:

yml
# Use system certificate store
pg:
  tls: {}

# Skip certificate verification (testing only)
pg:
  tls:
    insecure_skip_verify: true

To connect without TLS, remove the tls block. Uptrace refuses a client tls block with insecure: true for pg, ch_cluster replicas, redis_cache, kafka, and self_monitoring. Only mailer.smtp.tls accepts insecure. Without a tls block, the PostgreSQL client uses the sslmode of pg.dsn, for example sslmode=disable, and connects in plaintext when there is no dsn.

Authentication

Seed data

Initial users, organizations, and projects are created when you run uptrace db seed, and can be modified through the UI afterward. Each entry has a key, and other entries refer to it with user_key, org_key, project_key, or org_user_key:

yml
seed_data:
  users:
    - key: admin_user
      name: System Administrator
      email: admin@mycompany.com
      password: ChangeThisPassword123!
      email_confirmed: true

  user_tokens:
    - key: admin_token
      user_key: admin_user
      token: secure_admin_token_here

  orgs:
    - key: main_org
      name: My Company

  org_users:
    - key: admin_org_membership
      org_key: main_org
      user_key: admin_user
      role: owner  # owner, admin, member, viewer, billing_manager, collaborator

  projects:
    - key: production_project
      name: Production Environment
      org_key: main_org

  project_tokens:
    - key: prod_token
      project_key: production_project
      token: prod_telemetry_secret  # Used in OTLP DSN

  project_users:
    - key: admin_project_access
      project_key: production_project
      org_user_key: admin_org_membership  # an org_users key, not a user key
      perm_level: admin  # none, view, edit, admin

Auth settings

yml
auth:
  # Disable all login routes, including SSO
  #disabled: true

  # Block new password registrations
  #sign_up: false

  # Block password sign-ins; SSO remains available
  #sign_in: false

  # Restrict registration to a domain
  #email_regexp: '^.+@mycompany\.com$'
ScenarioSetting
Disable all login routesdisabled: true
No new registrationssign_up: false
No password sign-inssign_in: false
Restrict to company domainemail_regexp: '^.+@mycompany\.com$'

Single Sign-On

Uptrace supports enterprise identity providers:

Processing pipelines

Uptrace processes telemetry through parallel pipelines — one each for spans, span links, logs, events, and metrics. Each pipeline has its own block under pipelines. For detailed tuning guidance, see Scaling Uptrace.

yml
pipelines:
  spans:
    max_threads: 16             # Processing goroutines (default: CPU cores)
    ch_max_insert_size: 10000   # Records per INSERT batch
    max_buffered_bytes: 536870912  # 512 MiB buffer cap

  span_links:
    disabled: false
    max_threads: 2
    ch_max_insert_size: 5000
    max_buffered_bytes: 67108864  # 64 MiB

  logs:
    max_threads: 12
    ch_max_insert_size: 15000
    max_buffered_bytes: 402653184  # 384 MiB

  events:
    max_threads: 4
    ch_max_insert_size: 5000
    max_buffered_bytes: 134217728  # 128 MiB

  metrics:
    max_threads: 8
    ch_max_insert_size: 10000
    max_buffered_bytes: 268435456  # 256 MiB
    max_cumulative_timeseries: 2000000  # Cumulative-to-delta conversion limit

Query limits

Prevent resource exhaustion from expensive queries:

yml
trace:
  query_limit: 500000             # Max spans per query
  max_memory_usage_bytes: 500000000  # 500 MB per query

Redis cache

yml
redis_cache:
  addrs:
    alpha: redis-1:6379
    bravo: redis-2:6379
  username: ''
  password: 'redis_password'
  db: 0
  dial_timeout: 5s
  read_timeout: 3s
  write_timeout: 3s
  #tls:
  #  insecure_skip_verify: false

Features

MCP and OAuth

The MCP server accepts requests at /mcp/<project_id>. Browser sign-in uses the built-in OAuth authorization server. API tokens remain available when browser sign-in is disabled.

yml
mcp:
  disabled: false
  http_timeout: 30s
  defaults:
    limit: 100
    lookback: 1h

oauth:
  disabled: false
  access_token_ttl: 1h
  refresh_token_ttl: 720h
  dcr: open

mcp.disabled turns off the MCP endpoint. mcp.http_timeout limits requests from MCP tools to the Uptrace API. The query defaults set the result limit and time window when a tool call omits them.

oauth.disabled turns off browser sign-in for MCP clients, but API tokens still work. Access tokens expire after access_token_ttl. Refresh tokens expire after refresh_token_ttl, so a client must ask for approval again. dcr: off refuses dynamic client registration; common MCP clients use the default open setting.

Generative model client

The optional genai client runs structured tasks such as incident grouping. Set protocol to enable it, and choose a model. Leave protocol unset to keep these tasks off.

yml
genai:
  protocol: openai
  api_key: ${GENAI_API_KEY}
  model: YOUR_MODEL
  timeout: 60s
  max_retries: 3

Use openai for the OpenAI API or a server that enforces JSON schemas. Use openai-compat for a JSON-mode server such as Ollama; this protocol requires base_url. Use anthropic for the Anthropic Messages API. api_key can be empty when base_url points to a server without authentication. Run uptrace genai check to test the configured endpoint.

Alerting and service graph

yml
alerting:
  #monitors: false       # Stop the monitor runners
  #notifications: false  # Stop delivering alert notifications

  #incidents:
  #  disabled: true      # Stop grouping alerts into incidents

pipelines:
  service_graph:
    #disabled: true  # Disable service graph processing

self_monitoring:
  disabled: false
  dsn: http://project1_secret@uptrace.local/2?grpc=4317

Source maps

Configure JavaScript source map processing to resolve minified stack traces:

yml
sourcemaps:
  #disabled: true
  #upload: false
  #http_timeout: 5s
  #source_cache_size: 100000
  #consumer_cache_size: 4
  #error_cache_size: 100000
OptionDefaultDescription
disabledfalseDisable all sourcemap processing
uploadtrueAccept user-uploaded source maps (storage and resolution)
http_timeout5sTimeout for fetching discovered source maps over HTTP (max 30s)
source_cache_sizescales with CPUMax resolved source positions to cache
consumer_cache_sizescales with CPUMax parsed source map files in memory
error_cache_sizescales with CPUMax failed lookups to cache

Notifications

Email (SMTP)

yml
mailer:
  smtp:
    enabled: false
    host: localhost
    port: 1025
    username: mailhog
    password: mailhog
    from: no-reply@uptrace.local
    #tls: { insecure: true }

Gmail example:

  1. Generate an app-specific password in Gmail settings.
  2. Configure Uptrace:
yml
mailer:
  smtp:
    enabled: true
    host: smtp.gmail.com
    port: 587
    username: youraccount@gmail.com
    password: your_app_specific_password
    from: 'youraccount@gmail.com'

Without a tls block, Uptrace uses STARTTLS when the server offers it. With a tls block, TLS is required: port 465 uses implicit TLS (SMTPS), and any other port uses STARTTLS. tls: { insecure: true } turns TLS off.

Telegram

yml
telegram:
  bot_token: 'your_telegram_bot_token'

Setup guide: BotFather.

System settings

Logging

yml
logging:
  level: INFO  # DEBUG, INFO, WARN, ERROR

Premium license

yml
license:
  key: 'your_premium_license_key'

Premium features: ClickHouse distributed tables, advanced SSO, priority support.

Deployment

Production checklist

Security:

  • Change all default passwords and tokens in seed_data
  • Configure TLS for all connections
  • Set up auth restrictions (auth.email_regexp)
  • Configure firewall rules

High availability:

  • Deploy multiple Uptrace instances behind a load balancer
  • Configure PostgreSQL with read replicas
  • Set up ClickHouse replication (minimum 3 nodes)
  • Configure Redis for caching and session storage
  • Set up database backups

Performance:

  • Tune processing pipelines based on ingestion volume (see Scaling Uptrace)
  • Configure data retention policies
  • Set up monitoring for Uptrace itself

Reverse proxy

yml
site:
  url: https://uptrace.mycompany.com       # Main deployment
  # url: https://mycompany.com/uptrace     # Subpath deployment

When deploying under a subpath (e.g., /uptrace), the reverse proxy must strip the prefix before forwarding. Rewrite /uptrace(/|$)(.*) to /$2:

nginx Nginx
location ~ ^/uptrace(/|$) {
    rewrite ^/uptrace$ / break;
    rewrite ^/uptrace(/.*)$ $1 break;
    proxy_pass http://uptrace:14318;
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto $scheme;
}
haproxy HAProxy
frontend http_front
    bind *:80
    acl is_uptrace path_beg /uptrace
    use_backend uptrace_backend if is_uptrace

backend uptrace_backend
    http-request replace-path /uptrace(/|$)(.*) /\2
    http-request set-header X-Forwarded-Proto https
    http-request set-header X-Forwarded-For %[src]
    server uptrace uptrace:14318 check
yaml Traefik
labels:
  - "traefik.enable=true"
  - "traefik.http.routers.uptrace.rule=PathPrefix(`/uptrace`)"
  - "traefik.http.routers.uptrace.middlewares=uptrace-strip"
  - "traefik.http.middlewares.uptrace-strip.stripprefix.prefixes=/uptrace"
  - "traefik.http.services.uptrace.loadbalancer.server.port=14318"

Health check endpoints: GET /health/live for liveness and GET /health/ready for readiness. See health endpoints.

Scaling

For processing pipeline tuning, ClickHouse insert optimization, sharding, and resource sizing, see Scaling Uptrace.