== shipped role scripts (bin/)
run-all-in-one.sh
run-beat.sh
run-celery-with-beat.sh
run-celery.sh
run-granian.sh
run-migrate.sh
run-uwsgi.sh
run-web.sh
run-worker.sh
start.sh
tune-malloc.sh
-- bin/start.sh
#!/usr/bin/env sh
set -e

SERVER_ROLE="${SERVER_ROLE:-web}"
if [ "$SERVER_ROLE" = "web" ] && [ "${GLITCHTIP_EMBED_WORKER}" = "true" ]; then
    SERVER_ROLE="all_in_one"
fi
HEROKU_DYNO="${DYNO:-no}"

case "$HEROKU_DYNO" in
    web*) ./manage.py migrate ;;
    worker*) SERVER_ROLE=worker ;;
esac

case $SERVER_ROLE in
    web)
        SCRIPT="./bin/run-web.sh"
        ;;
    worker)
        SCRIPT="./bin/run-worker.sh"
        ;;
    worker_with_beat)
        SCRIPT="./bin/run-worker.sh"
        ;;
    all_in_one)
        SCRIPT="./bin/run-all-in-one.sh"
        ;;
    *)
        echo "Unknown server role provided: $SERVER_ROLE. Should be web|worker|all_in_one."
        exit 1
        ;;
esac

. "$SCRIPT"
-- bin/run-worker.sh
#!/usr/bin/env bash
export IS_WORKER="true"
export LOG_LEVEL=${LOG_LEVEL:-INFO}
set -e

. "$(dirname "$0")/tune-malloc.sh"

exec ./manage.py runworker --scheduler
-- bin/run-all-in-one.sh (head)
#!/usr/bin/env sh
set -e

. "$(dirname "$0")/tune-malloc.sh"

# Run initialization commands unless SKIP_INIT is set
# Set SKIP_INIT=true when running migrations as a pre-deploy hook
if [ "${SKIP_INIT}" != "True" ] && [ "${SKIP_INIT}" != "true" ] && [ "${SKIP_INIT}" != "1" ]; then
    if [ -n "$MAINTENANCE_DATABASE_URL" ]; then
        DB_FLAG="--database maintenance"
    else
        DB_FLAG=""
    fi
    python manage.py migrate --no-input --skip-checks $DB_FLAG
    python manage.py maintain_partitions

    if [ "$GLITCHTIP_BOOTSTRAP_DEV" = "True" ] || [ "$GLITCHTIP_BOOTSTRAP_DEV" = "true" ] || [ "$GLITCHTIP_BOOTSTRAP_DEV" = "1" ]; then
        python manage.py bootstrap_dev
    fi

    # Create cache table if django.contrib.sessions is installed
    python -c "import os, django; os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'glitchtip.settings'); django.setup(); from django.conf import settings; from django.core.management import call_command; call_command('createcachetable') if 'django.contrib.sessions' in settings.INSTALLED_APPS else None"
fi

# Enable embedded worker
export GLITCHTIP_EMBED_WORKER=true

# Granian settings

WORKERS=${GRANIAN_WORKERS:-${WEB_CONCURRENCY:-1}}

HOST=${GRANIAN_HOST:-0.0.0.0}
PORT=${GRANIAN_PORT:-${PORT:-8000}}

G_LOG_LEVEL=${GRANIAN_LOG_LEVEL:-INFO}

# Serve static files by default if the directory exists
if [ -n "$GRANIAN_STATIC_PATH_MOUNT" ]; then
    export GRANIAN_STATIC_PATH_MOUNT
elif [ -d "static" ]; then
== effective settings (manage.py shell)
import os
from django.conf import settings as s
from django_vtasks.conf import settings as v
print('\''GLITCHTIP_RUST_INGEST'\'', getattr(s, '\''GLITCHTIP_RUST_INGEST'\'', '\''n/a (setting absent)'\''))
print('\''TASKS'\'', s.TASKS)
print('\''VTASKS_QUEUES'\'', s.VTASKS_QUEUES)
print('\''VTASKS_VALKEY_PREFIX'\'', v.VTASKS_VALKEY_PREFIX)
print('\''VTASKS_MAX_RESCUES'\'', v.VTASKS_MAX_RESCUES)
print('\''VTASKS_CONCURRENCY'\'', v.VTASKS_CONCURRENCY)
print('\''VALKEY_URL'\'', s.VALKEY_URL)
print('\''CACHES'\'', s.CACHES['\''default'\'']['\''BACKEND'\''])
print('\''BILLING_ENABLED'\'', s.BILLING_ENABLED)
print('\''GLITCHTIP_THROTTLE_CHECK_INTERVAL'\'', s.GLITCHTIP_THROTTLE_CHECK_INTERVAL)
print('\''ALLOWED_HOSTS'\'', s.ALLOWED_HOSTS)
print('\''env SERVER_ROLE'\'', os.environ.get('\''SERVER_ROLE'\''), '\''GLITCHTIP_EMBED_WORKER'\'', os.environ.get('\''GLITCHTIP_EMBED_WORKER'\''))
'
import os
from django.conf import settings as s
from django_vtasks.conf import settings as v
print('\''GLITCHTIP_RUST_INGEST'\'', getattr(s, '\''GLITCHTIP_RUST_INGEST'\'', '\''n/a (setting absent)'\''))
print('\''TASKS'\'', s.TASKS)
print('\''VTASKS_QUEUES'\'', s.VTASKS_QUEUES)
print('\''VTASKS_VALKEY_PREFIX'\'', v.VTASKS_VALKEY_PREFIX)
print('\''VTASKS_MAX_RESCUES'\'', v.VTASKS_MAX_RESCUES)
print('\''VTASKS_CONCURRENCY'\'', v.VTASKS_CONCURRENCY)
print('\''VALKEY_URL'\'', s.VALKEY_URL)
print('\''CACHES'\'', s.CACHES['\''default'\'']['\''BACKEND'\''])
print('\''BILLING_ENABLED'\'', s.BILLING_ENABLED)
print('\''GLITCHTIP_THROTTLE_CHECK_INTERVAL'\'', s.GLITCHTIP_THROTTLE_CHECK_INTERVAL)
print('\''ALLOWED_HOSTS'\'', s.ALLOWED_HOSTS)
print('\''env SERVER_ROLE'\'', os.environ.get('\''SERVER_ROLE'\''), '\''GLITCHTIP_EMBED_WORKER'\'', os.environ.get('\''GLITCHTIP_EMBED_WORKER'\''))
'
/usr/local/lib/python3.14/importlib/__init__.py:88: RuntimeWarning: ALLOWED_HOSTS is the wildcard default. Restrict to known hostnames via the ALLOWED_HOSTS env var (comma-separated) in production deployments.
  return _bootstrap._gcd_import(name[level:], package, level)
67 objects imported automatically (use -v 2 for details).

GLITCHTIP_RUST_INGEST False
TASKS {'default': {'BACKEND': 'django_vtasks.backends.valkey.ValkeyTaskBackend', 'OPTIONS': {'cache_alias': 'default'}}}
VTASKS_QUEUES {'default': {}, 'ingest': {'worker_concurrency': 12, 'batch': {'count': 25, 'timeout': 2.0}}}
VTASKS_VALKEY_PREFIX {vt}:
VTASKS_MAX_RESCUES 0
VTASKS_CONCURRENCY 20
VALKEY_URL redis://valkey:6379
CACHES django_vcache.backend.ValkeyCache
BILLING_ENABLED False
GLITCHTIP_THROTTLE_CHECK_INTERVAL 5000
ALLOWED_HOSTS ['*']
env SERVER_ROLE all_in_one GLITCHTIP_EMBED_WORKER None
== restart policies + docker healthchecks
/glitchtip-bench-web-1 restart=unless-stopped health=none
/glitchtip-bench-postgres-1 restart=unless-stopped health=none
/glitchtip-bench-valkey-1 restart=unless-stopped health=none
== valkey persistence (defaults of the valkey/valkey image; no volume in the vendor compose)
save
3600 1 300 100 60 10000
appendonly
no
dir
/data
valkey mounts=[]
== postgres event tables
issue_events_comment
issue_events_issue
issue_events_issueaggregate
issue_events_issueaggregate_20260914
issue_events_issueaggregate_20260914_h0
issue_events_issueaggregate_20260914_h1
issue_events_issueaggregate_20260921
issue_events_issueaggregate_20260921_h0
issue_events_issueaggregate_20260921_h1
issue_events_issueaggregate_20260928
issue_events_issueaggregate_20260928_h0
issue_events_issueaggregate_20260928_h1
issue_events_issueaggregate_20261005
issue_events_issueaggregate_20261005_h0
issue_events_issueaggregate_20261005_h1
issue_events_issueevent
issue_events_issueevent_20260914
issue_events_issueevent_20260914_h0
issue_events_issueevent_20260914_h1
issue_events_issueevent_20260915
issue_events_issueevent_20260915_h0
issue_events_issueevent_20260915_h1
issue_events_issueevent_20260916
issue_events_issueevent_20260916_h0
issue_events_issueevent_20260916_h1
issue_events_issueevent_20260917
issue_events_issueevent_20260917_h0
issue_events_issueevent_20260917_h1
issue_events_issueevent_20260918
issue_events_issueevent_20260918_h0
issue_events_issueevent_20260918_h1
issue_events_issueevent_20260919
issue_events_issueevent_20260919_h0
issue_events_issueevent_20260919_h1
issue_events_issueevent_20260920
issue_events_issueevent_20260920_h0
issue_events_issueevent_20260920_h1
issue_events_issuehash
issue_events_issueindex
issue_events_issueindex_h0
issue_events_issueindex_h1
issue_events_issuetag
issue_events_issuetag_20260914
issue_events_issuetag_20260914_h0
issue_events_issuetag_20260914_h1
issue_events_issuetag_20260921
issue_events_issuetag_20260921_h0
issue_events_issuetag_20260921_h1
issue_events_issuetag_20260928
issue_events_issuetag_20260928_h0
issue_events_issuetag_20260928_h1
issue_events_issuetag_20261005
issue_events_issuetag_20261005_h0
issue_events_issuetag_20261005_h1
issue_events_tagkey
issue_events_tagvalue
issue_events_userreport
projects_issueeventprojecthourlystatistic
projects_issueeventprojecthourlystatistic_20260914
projects_issueeventprojecthourlystatistic_20260914_h0
projects_issueeventprojecthourlystatistic_20260914_h1
projects_issueeventprojecthourlystatistic_20260921
projects_issueeventprojecthourlystatistic_20260921_h0
projects_issueeventprojecthourlystatistic_20260921_h1
projects_issueeventprojecthourlystatistic_20260928
projects_issueeventprojecthourlystatistic_20260928_h0
projects_issueeventprojecthourlystatistic_20260928_h1
projects_issueeventprojecthourlystatistic_20261005
projects_issueeventprojecthourlystatistic_20261005_h0
projects_issueeventprojecthourlystatistic_20261005_h1
projects_logprojecthourlystatistic
projects_logprojecthourlystatistic_20260914
projects_logprojecthourlystatistic_20260914_h0
projects_logprojecthourlystatistic_20260914_h1
projects_logprojecthourlystatistic_20260921
projects_logprojecthourlystatistic_20260921_h0
projects_logprojecthourlystatistic_20260921_h1
projects_logprojecthourlystatistic_20260928
projects_logprojecthourlystatistic_20260928_h0
projects_logprojecthourlystatistic_20260928_h1
projects_logprojecthourlystatistic_20261005
projects_logprojecthourlystatistic_20261005_h0
projects_logprojecthourlystatistic_20261005_h1
projects_project
projects_projectcounter
projects_projectkey
projects_transactioneventprojecthourlystatistic
projects_transactioneventprojecthourlystatistic_20260914
projects_transactioneventprojecthourlystatistic_20260914_h0
projects_transactioneventprojecthourlystatistic_20260914_h1
projects_transactioneventprojecthourlystatistic_20260921
projects_transactioneventprojecthourlystatistic_20260921_h0
projects_transactioneventprojecthourlystatistic_20260921_h1
projects_transactioneventprojecthourlystatistic_20260928
projects_transactioneventprojecthourlystatistic_20260928_h0
projects_transactioneventprojecthourlystatistic_20260928_h1
projects_transactioneventprojecthourlystatistic_20261005
projects_transactioneventprojecthourlystatistic_20261005_h0
projects_transactioneventprojecthourlystatistic_20261005_h1
projects_userprojectalert
-- partitions of issue_events_issueevent
issue_events_issueevent_20260914
issue_events_issueevent_20260915
issue_events_issueevent_20260916
issue_events_issueevent_20260917
issue_events_issueevent_20260918
issue_events_issueevent_20260919
issue_events_issueevent_20260920
                        Partitioned table "public.issue_events_issueevent"
     Column      |           Type           | Collation | Nullable |           Default            
-----------------+--------------------------+-----------+----------+------------------------------
 id              | uuid                     |           | not null | uuid_generate_v7()
 event_id        | uuid                     |           |          | 
 timestamp       | timestamp with time zone |           | not null | 
 created         | timestamp with time zone |           | not null | timezone('utc'::text, now())
 issue_id        | bigint                   |           | not null | 
 organization_id | bigint                   |           | not null | 
 release_id      | bigint                   |           |          | 
 type            | smallint                 |           | not null | 0
 level           | smallint                 |           | not null | 4
 title           | character varying(255)   |           | not null | 
 transaction     | character varying(1024)  |           | not null | 
 data            | jsonb                    |           | not null | 
 tags            | jsonb                    |           | not null | 
 hashes          | text[]                   |           | not null | ARRAY[]::text[]
Partition key: RANGE (id)
Indexes:
    "issue_events_issueevent_pkey" PRIMARY KEY, btree (id, organization_id)
    "issueevent_event_id_idx" btree (event_id) WHERE event_id IS NOT NULL
    "issueevent_hashes_idx" gin (hashes)
    "issueevent_issue_id_idx" btree (issue_id, id DESC)
    "issueevent_release_idx" btree (release_id)
Check constraints:
    "issue_events_issueevent_level_check" CHECK (level >= 0 AND level <= 5)
    "issue_events_issueevent_type_check" CHECK (type >= 0)
Foreign-key constraints:
    "issue_events_issueevent_organization_id_fkey" FOREIGN KEY (organization_id) REFERENCES organizations_ext_organization(id) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED
    "issue_events_issueevent_release_id_fkey" FOREIGN KEY (release_id) REFERENCES releases_release(id) ON DELETE SET NULL DEFERRABLE INITIALLY DEFERRED
Number of partitions: 7 (Use \d+ to list them.)

== processes in web (all_in_one)
UID                 PID                 PPID                C                   STIME               TTY                 TIME                CMD
5000                2053                2003                0                   13:18               ?                   00:00:00            /usr/local/bin/python3 /usr/local/bin/granian --interface asgi glitchtip.asgi:application --host 0.0.0.0 --port 8000 --workers 1 --log-level INFO --no-ws
5000                2190                2053                1                   13:18               ?                   00:00:00            /usr/local/bin/python3 -c from multiprocessing.resource_tracker import main;main(7)
5000                2191                2053                37                  13:18               ?                   00:00:04            /usr/local/bin/python3 -c from multiprocessing.spawn import spawn_main; spawn_main(tracker_fd=8, pipe_handle=10) --multiprocessing-fork
== valkey keys right after the sanity send
{vt}:scheduler:vtasks_scheduler_lock
{vt}:scheduler:vtasks_last_run:send-alert-notifications
{vt}:scheduler:vtasks_last_run:uptime-dispatch-checks
{vt}:scheduler:vtasks_promote_lock
{vt}:alive:e6c689a51c8e-30
{vt}:scheduler:vtasks_last_run:perform-maintenance
:1:uptime_counter
:1:uuid8f10191e312842e7b9d0c5cc652be9f5
