AutomationFlowsEmail & Gmail › Quantra - Daily Usage Monitoring

Quantra - Daily Usage Monitoring

Quantra - Daily Usage Monitoring. Uses postgres, gmail. Scheduled trigger; 10 nodes.

Cron / scheduled trigger★★★★☆ complexity10 nodesPostgresGmail
Email & Gmail Trigger: Cron / scheduled Nodes: 10 Complexity: ★★★★☆ Added:

This workflow follows the Gmail → Postgres recipe pattern — see all workflows that pair these two integrations.

The workflow JSON

Copy or download the full n8n JSON below. Paste it into a new n8n workflow, add your credentials, activate. Full import guide →

Download .json
{
  "name": "Quantra - Daily Usage Monitoring",
  "nodes": [
    {
      "parameters": {
        "rule": {
          "interval": [
            {
              "triggerAtHour": 8,
              "triggerAtMinute": 0
            }
          ]
        }
      },
      "id": "trigger",
      "name": "Daily 8AM Report",
      "type": "n8n-nodes-base.scheduleTrigger",
      "typeVersion": 1.2,
      "position": [
        0,
        200
      ]
    },
    {
      "parameters": {
        "operation": "executeQuery",
        "query": "SELECT\n  schemaname,\n  tablename,\n  pg_size_pretty(pg_total_relation_size(schemaname || '.' || tablename)) as total_size,\n  pg_total_relation_size(schemaname || '.' || tablename) as size_bytes\nFROM pg_tables\nWHERE schemaname = 'public'\nORDER BY pg_total_relation_size(schemaname || '.' || tablename) DESC\nLIMIT 20;",
        "options": {}
      },
      "id": "get-table-sizes",
      "name": "Get Table Sizes",
      "type": "n8n-nodes-base.postgres",
      "typeVersion": 2.5,
      "position": [
        250,
        0
      ],
      "credentials": {
        "postgres": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "operation": "executeQuery",
        "query": "SELECT\n  'time_entries' as table_name, COUNT(*) as row_count FROM time_entries\nUNION ALL\nSELECT 'notifications', COUNT(*) FROM notifications\nUNION ALL\nSELECT 'messages', COUNT(*) FROM messages\nUNION ALL\nSELECT 'shifts', COUNT(*) FROM shifts\nUNION ALL\nSELECT 'quantra_actions', COUNT(*) FROM quantra_actions\nUNION ALL\nSELECT 'employees', COUNT(*) FROM employees\nUNION ALL\nSELECT 'companies', COUNT(*) FROM companies\nUNION ALL\nSELECT 'workflow_executions', COUNT(*) FROM workflow_executions\nORDER BY row_count DESC;",
        "options": {}
      },
      "id": "get-row-counts",
      "name": "Get Row Counts",
      "type": "n8n-nodes-base.postgres",
      "typeVersion": 2.5,
      "position": [
        250,
        150
      ],
      "credentials": {
        "postgres": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "operation": "executeQuery",
        "query": "SELECT\n  pg_size_pretty(pg_database_size(current_database())) as database_size,\n  pg_database_size(current_database()) as size_bytes,\n  (SELECT count(*) FROM pg_stat_activity WHERE state = 'active') as active_connections,\n  (SELECT count(*) FROM pg_stat_activity) as total_connections;",
        "options": {}
      },
      "id": "get-database-stats",
      "name": "Get Database Stats",
      "type": "n8n-nodes-base.postgres",
      "typeVersion": 2.5,
      "position": [
        250,
        300
      ],
      "credentials": {
        "postgres": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "operation": "executeQuery",
        "query": "SELECT\n  'time_entries' as table_name, \n  COUNT(*) as created_24h\nFROM time_entries WHERE created_at > NOW() - INTERVAL '24 hours'\nUNION ALL\nSELECT 'notifications', COUNT(*)\nFROM notifications WHERE created_at > NOW() - INTERVAL '24 hours'\nUNION ALL\nSELECT 'messages', COUNT(*)\nFROM messages WHERE created_at > NOW() - INTERVAL '24 hours'\nUNION ALL\nSELECT 'quantra_actions', COUNT(*)\nFROM quantra_actions WHERE created_at > NOW() - INTERVAL '24 hours';",
        "options": {}
      },
      "id": "get-growth-metrics",
      "name": "Get Growth Metrics",
      "type": "n8n-nodes-base.postgres",
      "typeVersion": 2.5,
      "position": [
        250,
        450
      ],
      "credentials": {
        "postgres": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "mode": "append"
      },
      "id": "merge-results",
      "name": "Wait For All",
      "type": "n8n-nodes-base.merge",
      "typeVersion": 3,
      "position": [
        500,
        200
      ]
    },
    {
      "parameters": {
        "jsCode": "// Get all items\nconst items = $input.all();\n\n// Separate data by type\nlet dbStats = null;\nconst tableSizes = [];\nconst rowCounts = [];\nconst growthMetrics = [];\n\nfor (const item of items) {\n  const data = item.json;\n  \n  if (data.database_size) {\n    dbStats = data;\n  } else if (data.total_size && data.tablename) {\n    tableSizes.push(data);\n  } else if (data.row_count !== undefined) {\n    rowCounts.push(data);\n  } else if (data.created_24h !== undefined) {\n    growthMetrics.push(data);\n  }\n}\n\n// Calculate alerts\nconst alerts = [];\nconst sizeMB = dbStats ? dbStats.size_bytes / (1024 * 1024) : 0;\nconst sizePercent = (sizeMB / 500) * 100; // 500MB free tier\n\nif (sizeMB > 450) {\n  alerts.push({ level: 'critical', message: `Database at ${sizePercent.toFixed(1)}% (${dbStats.database_size}) - above 90% limit!` });\n} else if (sizeMB > 375) {\n  alerts.push({ level: 'warning', message: `Database at ${sizePercent.toFixed(1)}% (${dbStats.database_size}) - approaching limit` });\n}\n\nif (dbStats && dbStats.active_connections > 15) {\n  alerts.push({ level: 'warning', message: `High active connections: ${dbStats.active_connections}` });\n}\n\nconst totalRows = rowCounts.reduce((sum, r) => sum + (parseInt(r.row_count) || 0), 0);\nconst total24h = growthMetrics.reduce((sum, g) => sum + (parseInt(g.created_24h) || 0), 0);\n\nreturn {\n  json: {\n    report_date: new Date().toLocaleDateString('en-US', { weekday: 'long', year: 'numeric', month: 'long', day: 'numeric' }),\n    timestamp: new Date().toISOString(),\n    database: {\n      size: dbStats ? dbStats.database_size : 'Unknown',\n      size_bytes: dbStats ? dbStats.size_bytes : 0,\n      size_mb: sizeMB.toFixed(2),\n      size_percent: sizePercent.toFixed(1),\n      active_connections: dbStats ? dbStats.active_connections : 0,\n      total_connections: dbStats ? dbStats.total_connections : 0\n    },\n    table_sizes: tableSizes.slice(0, 5),\n    row_counts: rowCounts,\n    growth_24h: growthMetrics,\n    total_rows: totalRows,\n    total_24h_inserts: total24h,\n    alerts: alerts,\n    has_alerts: alerts.length > 0,\n    has_critical: alerts.some(a => a.level === 'critical')\n  }\n};"
      },
      "id": "analyze-data",
      "name": "Analyze Data",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        700,
        200
      ]
    },
    {
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": true,
            "leftValue": "",
            "typeValidation": "strict"
          },
          "conditions": [
            {
              "id": "has-alerts",
              "leftValue": "={{ $json.has_alerts }}",
              "rightValue": true,
              "operator": {
                "type": "boolean",
                "operation": "equals"
              }
            }
          ],
          "combinator": "and"
        },
        "options": {}
      },
      "id": "check-alerts",
      "name": "Has Alerts?",
      "type": "n8n-nodes-base.if",
      "typeVersion": 2.1,
      "position": [
        900,
        200
      ]
    },
    {
      "parameters": {
        "sendTo": "danavgeissler@quantrahq.com",
        "subject": "=\u26a0\ufe0f ALERT: Quantra Database Alert - {{ $json.report_date }}",
        "message": "=<h2 style=\"color: #dc2626;\">\u26a0\ufe0f Quantra Database Alert</h2>\n\n<p><strong>Date:</strong> {{ $json.report_date }}</p>\n\n<div style=\"padding: 15px; background: #fef2f2; border-left: 4px solid #dc2626; margin: 20px 0;\">\n<h3 style=\"margin-top: 0; color: #dc2626;\">Alerts Detected</h3>\n<ul>\n{{ $json.alerts.map(a => '<li style=\"color: ' + (a.level === 'critical' ? '#dc2626' : '#f59e0b') + ';\"><strong>' + a.level.toUpperCase() + ':</strong> ' + a.message + '</li>').join('') }}\n</ul>\n</div>\n\n<h3>Database Overview</h3>\n<table border=\"1\" cellpadding=\"10\" cellspacing=\"0\" style=\"border-collapse: collapse;\">\n  <tr><td><strong>Database Size</strong></td><td>{{ $json.database.size }} ({{ $json.database.size_percent }}% of 500MB limit)</td></tr>\n  <tr><td><strong>Total Rows</strong></td><td>{{ $json.total_rows.toLocaleString() }}</td></tr>\n  <tr><td><strong>Connections</strong></td><td>{{ $json.database.active_connections }} active / {{ $json.database.total_connections }} total</td></tr>\n  <tr><td><strong>24h New Records</strong></td><td>{{ $json.total_24h_inserts }}</td></tr>\n</table>\n\n<h3>Top Tables by Size</h3>\n<table border=\"1\" cellpadding=\"10\" cellspacing=\"0\" style=\"border-collapse: collapse; width: 100%;\">\n  <tr style=\"background: #f3f4f6;\"><th>Table</th><th>Size</th></tr>\n  {{ $json.table_sizes.map(t => '<tr><td>' + t.tablename + '</td><td>' + t.total_size + '</td></tr>').join('') }}\n</table>\n\n<p style=\"margin-top: 20px;\"><strong>Action Required:</strong> Please review and consider running cleanup or upgrading your plan.</p>\n\n<hr style=\"margin-top: 30px;\">\n<p style=\"color: #666; font-size: 12px;\">Quantra Autonomous Worker - Automated Monitoring</p>",
        "options": {
          "appendAttribution": false
        }
      },
      "id": "gmail-alert",
      "name": "Send Alert Email",
      "type": "n8n-nodes-base.gmail",
      "typeVersion": 2.1,
      "position": [
        1150,
        100
      ],
      "credentials": {
        "gmailOAuth2": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "sendTo": "danavgeissler@quantrahq.com",
        "subject": "=\ud83d\udcca Quantra Daily Report - {{ $json.report_date }}",
        "message": "=<h2>\ud83d\udcca Daily Database Report</h2>\n\n<p><strong>Date:</strong> {{ $json.report_date }}</p>\n\n<h3>Overview</h3>\n<table border=\"1\" cellpadding=\"10\" cellspacing=\"0\" style=\"border-collapse: collapse;\">\n  <tr><td><strong>Database Size</strong></td><td>{{ $json.database.size }} ({{ $json.database.size_percent }}% of limit)</td></tr>\n  <tr><td><strong>Total Rows</strong></td><td>{{ $json.total_rows.toLocaleString() }}</td></tr>\n  <tr><td><strong>Active Connections</strong></td><td>{{ $json.database.active_connections }}</td></tr>\n  <tr><td><strong>24h New Records</strong></td><td>{{ $json.total_24h_inserts }}</td></tr>\n</table>\n\n<h3>Top 5 Tables by Size</h3>\n<table border=\"1\" cellpadding=\"10\" cellspacing=\"0\" style=\"border-collapse: collapse; width: 100%;\">\n  <tr style=\"background: #f3f4f6;\"><th>Table</th><th>Size</th></tr>\n  {{ $json.table_sizes.map(t => '<tr><td>' + t.tablename + '</td><td>' + t.total_size + '</td></tr>').join('') }}\n</table>\n\n<h3>24h Activity</h3>\n<table border=\"1\" cellpadding=\"10\" cellspacing=\"0\" style=\"border-collapse: collapse; width: 100%;\">\n  <tr style=\"background: #f3f4f6;\"><th>Table</th><th>New Rows</th></tr>\n  {{ $json.growth_24h.map(g => '<tr><td>' + g.table_name + '</td><td>+' + g.created_24h + '</td></tr>').join('') }}\n</table>\n\n<div style=\"margin-top: 20px; padding: 15px; background: #d1fae5; border-radius: 5px;\">\n  \u2705 No alerts - all systems healthy\n</div>\n\n<hr style=\"margin-top: 30px;\">\n<p style=\"color: #666; font-size: 12px;\">Quantra Autonomous Worker - Automated Monitoring</p>",
        "options": {
          "appendAttribution": false
        }
      },
      "id": "gmail-daily-report",
      "name": "Send Daily Report",
      "type": "n8n-nodes-base.gmail",
      "typeVersion": 2.1,
      "position": [
        1150,
        300
      ],
      "credentials": {
        "gmailOAuth2": {
          "name": "<your credential>"
        }
      }
    }
  ],
  "connections": {
    "Daily 8AM Report": {
      "main": [
        [
          {
            "node": "Get Table Sizes",
            "type": "main",
            "index": 0
          },
          {
            "node": "Get Row Counts",
            "type": "main",
            "index": 0
          },
          {
            "node": "Get Database Stats",
            "type": "main",
            "index": 0
          },
          {
            "node": "Get Growth Metrics",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get Table Sizes": {
      "main": [
        [
          {
            "node": "Wait For All",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get Row Counts": {
      "main": [
        [
          {
            "node": "Wait For All",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get Database Stats": {
      "main": [
        [
          {
            "node": "Wait For All",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get Growth Metrics": {
      "main": [
        [
          {
            "node": "Wait For All",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Wait For All": {
      "main": [
        [
          {
            "node": "Analyze Data",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Analyze Data": {
      "main": [
        [
          {
            "node": "Has Alerts?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Has Alerts?": {
      "main": [
        [
          {
            "node": "Send Alert Email",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Send Daily Report",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  },
  "settings": {
    "executionOrder": "v1",
    "saveManualExecutions": true,
    "callerPolicy": "workflowsFromSameOwner"
  },
  "staticData": null,
  "tags": [
    {
      "name": "monitoring"
    },
    {
      "name": "scheduled"
    },
    {
      "name": "cost-optimization"
    },
    {
      "name": "gmail"
    }
  ],
  "versionId": "2"
}

Credentials you'll need

Each integration node will prompt for credentials when you import. We strip credential IDs before publishing — you'll add your own.

Pro

For the full experience including quality scoring and batch install features for each workflow upgrade to Pro

About this workflow

Quantra - Daily Usage Monitoring. Uses postgres, gmail. Scheduled trigger; 10 nodes.

Source: https://github.com/Weath123/Quantra-Autonomous-Worker/blob/c2ca42d25b36ab2ba894ff9f62cde2be4073bc95/n8n-workflows/02-usage-monitoring.json — original creator credit. Request a take-down →

More Email & Gmail workflows → · Browse all categories →

Related workflows

Workflows that share integrations, category, or trigger type with this one. All free to copy and import.

Email & Gmail

This workflow automates the complete end-to-end processing of daily revenue transactions for finance and accounting teams. It systematically retrieves, validates, and standardizes transaction data fro

HTTP Request, Gmail, Google Drive +2
Email & Gmail

Finance — Daily digest email. Uses postgres, gmail. Scheduled trigger; 8 nodes.

Postgres, Gmail
Email & Gmail

Monthly Energy Generation Report (Postgres → PDF → Email). Uses httpRequest, gmail, postgres. Scheduled trigger; 7 nodes.

HTTP Request, Gmail, Postgres
Email & Gmail

YOUR_ID 4. Uses gmail, googleDrive, googleSheets, httpRequest. Scheduled trigger; 53 nodes.

Gmail, Google Drive, Google Sheets +1
Email & Gmail

14310 Send Overdue Invoice Payment Reminders With Ifirma Gmail Postgrid And Slack. Uses httpRequest, stopAndError, slack, gmail. Scheduled trigger; 53 nodes.

HTTP Request, Stop And Error, Slack +1