productivity

Is Firefly III Down? Real-Time Status & Outage Checker

Is Firefly III Down? Real-Time Status & Outage Checker

Firefly III is an open-source personal finance manager with 17,000+ GitHub stars. It implements double-entry bookkeeping and supports budgets, categories, tags, recurring transactions, detailed reports, and a full REST API. Built on Laravel/PHP with MySQL or PostgreSQL, it was created by James Cole and is used by individuals and families who want deep, accurate financial tracking without sharing their data with commercial services. Firefly III serves as a self-hosted alternative to YNAB, Mint, and Personal Capital — with no subscription fee and complete data ownership.

When Firefly III goes down, recurring transactions stop being created, bills are not marked as paid, budgets become inaccessible, and any bank importers or integrations (the Firefly III Importer, Home Assistant, custom scripts) fail silently. Because financial data is sensitive and encrypted at rest, certain failure modes — like an app key rotation — can make all encrypted data permanently unreadable, making this one of the highest-stakes self-hosted applications to monitor carefully.

Quick Status Check

#!/bin/bash
# Firefly III health check script
# Tests API, PHP-FPM, database, Redis/session store, and cron job

FIREFLY_URL="${FIREFLY_URL:-http://localhost:8080}"
FIREFLY_TOKEN="${FIREFLY_TOKEN:-your-personal-access-token}"
DB_TYPE="${DB_TYPE:-mysql}"   # mysql or pgsql

echo "=== Firefly III Health Check ==="

# 1. Check PHP-FPM process
if pgrep -x php-fpm &>/dev/null; then
  echo "[OK] PHP-FPM process is running"
else
  echo "[FAIL] PHP-FPM process not detected"
fi

# 2. Check port 8080
if nc -z localhost 8080 2>/dev/null; then
  echo "[OK] Port 8080 is open"
else
  echo "[FAIL] Port 8080 is not responding"
fi

# 3. Firefly III API about (no auth required)
ABOUT=$(curl -sf "${FIREFLY_URL}/api/v1/about" 2>/dev/null)
if echo "$ABOUT" | grep -q '"version"'; then
  VERSION=$(echo "$ABOUT" | python3 -c "import sys,json; print(json.load(sys.stdin).get('data',{}).get('version','?'))" 2>/dev/null)
  echo "[OK] Firefly III API responding — version ${VERSION}"
else
  echo "[FAIL] API about endpoint not responding: ${ABOUT:0:120}"
fi

# 4. Check database connectivity
if [ "$DB_TYPE" = "mysql" ]; then
  if mysqladmin ping -h localhost --silent 2>/dev/null; then
    echo "[OK] MySQL is reachable"
  else
    echo "[FAIL] MySQL not responding"
  fi
elif [ "$DB_TYPE" = "pgsql" ]; then
  if pg_isready -h localhost -q 2>/dev/null; then
    echo "[OK] PostgreSQL is reachable"
  else
    echo "[FAIL] PostgreSQL not responding"
  fi
fi

# 5. Check Redis is responding (session store)
if redis-cli ping 2>/dev/null | grep -q "PONG"; then
  echo "[OK] Redis session store responding"
else
  echo "[WARN] Redis not responding — sessions may use file cache"
fi

# 6. Check cron job for recurring transactions
if crontab -l 2>/dev/null | grep -q "firefly\|artisan"; then
  echo "[OK] Firefly III cron entry found"
else
  echo "[WARN] No Firefly III cron entry found — recurring transactions may not run"
fi

echo "=== Check complete ==="

Python Health Check

#!/usr/bin/env python3
"""
Firefly III health check
Checks API about, account count, transaction count, budgets, and system configuration.
"""

import os
import sys
import requests

FIREFLY_URL = os.environ.get("FIREFLY_URL", "http://localhost:8080")
FIREFLY_TOKEN = os.environ.get("FIREFLY_TOKEN", "your-personal-access-token")
TIMEOUT = 15

AUTH_HEADERS = {
    "Authorization": f"Bearer {FIREFLY_TOKEN}",
    "Accept": "application/vnd.api+json",
    "Content-Type": "application/json",
}

def check(label: str, ok: bool, detail: str = "") -> bool:
    status = "OK  " if ok else "FAIL"
    msg = f"[{status}] {label}"
    if detail:
        msg += f" — {detail}"
    print(msg)
    return ok

results = []

# 1. API about (no auth required)
try:
    r = requests.get(f"{FIREFLY_URL}/api/v1/about", timeout=TIMEOUT)
    ok = r.status_code == 200
    data = r.json().get("data", {}) if ok else {}
    version = data.get("version", "unknown")
    api_version = data.get("api_version", "unknown")
    results.append(check("API about endpoint", ok, f"Firefly {version}, API {api_version}"))
except Exception as e:
    results.append(check("API about endpoint", False, str(e)))

# 2. Account count (requires Personal Access Token)
try:
    r = requests.get(
        f"{FIREFLY_URL}/api/v1/accounts",
        headers=AUTH_HEADERS,
        params={"limit": 1},
        timeout=TIMEOUT,
    )
    ok = r.status_code == 200
    total = r.json().get("meta", {}).get("pagination", {}).get("total", 0) if ok else 0
    results.append(check("Accounts accessible", ok, f"{total} account(s)"))
except Exception as e:
    results.append(check("Accounts accessible", False, str(e)))

# 3. Transaction count (most recent)
try:
    r = requests.get(
        f"{FIREFLY_URL}/api/v1/transactions",
        headers=AUTH_HEADERS,
        params={"type": "all", "limit": 1},
        timeout=TIMEOUT,
    )
    ok = r.status_code == 200
    total = r.json().get("meta", {}).get("pagination", {}).get("total", 0) if ok else 0
    results.append(check("Transactions accessible", ok, f"{total} transaction(s) in database"))
except Exception as e:
    results.append(check("Transactions accessible", False, str(e)))

# 4. Budget count
try:
    r = requests.get(
        f"{FIREFLY_URL}/api/v1/budgets",
        headers=AUTH_HEADERS,
        params={"limit": 1},
        timeout=TIMEOUT,
    )
    ok = r.status_code == 200
    total = r.json().get("meta", {}).get("pagination", {}).get("total", 0) if ok else 0
    results.append(check("Budgets accessible", ok, f"{total} budget(s) configured"))
except Exception as e:
    results.append(check("Budgets accessible", False, str(e)))

# 5. System configuration
try:
    r = requests.get(
        f"{FIREFLY_URL}/api/v1/configuration",
        headers=AUTH_HEADERS,
        timeout=TIMEOUT,
    )
    ok = r.status_code == 200
    config_data = r.json().get("data", []) if ok else []
    config_count = len(config_data)
    results.append(check("System configuration", ok, f"{config_count} config item(s) returned"))
except Exception as e:
    results.append(check("System configuration", False, str(e)))

# Summary
passed = sum(results)
total = len(results)
print(f"\n{'='*40}")
print(f"Firefly III health: {passed}/{total} checks passed")
if passed < total:
    print("Action required: review FAIL items above")
    sys.exit(1)
else:
    print("All systems operational")
    sys.exit(0)

Common Firefly III Outage Causes

SymptomLikely CauseResolution
All pages return 502 Bad Gateway PHP-FPM crash (OOM, fatal exception, or misconfigured worker pool) Restart PHP-FPM; increase memory limit; check /var/log/php-fpm/error.log for fatal errors
Transaction list timeouts on large datasets MySQL slow queries (missing indexes, large transaction table, no query cache) Run SHOW PROCESSLIST to find blocking queries; add indexes on transaction_journals; enable MySQL slow query log
Recurring transactions not created, bills not marked paid Cron job not running (artisan firefly-iii:cron not scheduled or broken) Add to crontab: * * * * * /usr/bin/php /var/www/firefly-iii/artisan firefly-iii:cron; check cron logs
All users suddenly logged out Redis session store lost (Redis restart wiped in-memory sessions) Use Redis with persistence (appendonly yes); or switch Firefly session driver to database in .env
All encrypted data unreadable — critical App key rotation (APP_KEY in .env changed — invalidates all Laravel-encrypted fields) Never change APP_KEY without a full database backup; restore original key from backup to recover data
Bank importer failing, no new transactions Firefly III Importer tool misconfigured or API token expired Regenerate Personal Access Token in Firefly UI; update importer config; check importer container logs

Architecture Overview

ComponentFunctionFailure Impact
Laravel/PHP application Core web app: routes, business logic, double-entry bookkeeping engine Complete outage; all pages and API calls fail
MySQL / PostgreSQL Stores all financial data: accounts, transactions, budgets, categories App returns 500; all financial data inaccessible
Redis (session store) Stores user sessions for web UI login persistence All users logged out on Redis restart; re-login required
Artisan cron job Runs recurring transaction creation, bill matching, and automated tasks Recurring transactions not created; bills not matched; automation stops silently
REST API (v1) Programmatic access for importers, Home Assistant, custom scripts All external integrations break; bank import stops; automations fail
Firefly III Importer Separate companion tool for importing from banks via CSV or GoCardless New bank transactions not imported; manual entry required

Uptime History

DateIncident TypeDurationImpact
2026-01 PHP-FPM OOM crash during large CSV import ~1 hr Complete service outage; all pages returned 502 until PHP-FPM restart
2025-11 Cron job silently stopped (Docker restart reset crontab) ~2 weeks Recurring transactions not created; discovered manually when bills not tracked
2025-08 MySQL slow query timeout on large transaction dataset ~3 hrs Transaction list pages timed out; budget reports unloadable
2025-07 Redis eviction cleared sessions (maxmemory-policy allkeys-lru) ~30 min All users logged out simultaneously; no data loss

Monitor Firefly III Automatically

Firefly III manages your most sensitive personal data — a silent cron failure means weeks of missing recurring transactions you only discover at month-end review, and an app key incident can make financial history permanently unreadable. External monitoring is not optional for a service this critical. ezmon.com monitors your Firefly III endpoints from multiple external probes and alerts your team via Slack, PagerDuty, or SMS the moment the API stops responding or the about endpoint returns an unexpected status.

Set up Firefly III monitoring free at ezmon.com →

firefly-iiipersonal-financeself-hostedbudgetingaccountingstatus-checker