AutomationFlowsSlack & Telegram › Expiry + Data Reminder Cron

Expiry + Data Reminder Cron

Expiry + Data Reminder Cron. Uses postgres, whatsApp. Scheduled trigger; 5 nodes.

Cron / scheduled trigger★★★★☆ complexity5 nodesPostgresWhatsApp
Slack & Telegram Trigger: Cron / scheduled Nodes: 5 Complexity: ★★★★☆ Added:

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": "Expiry + Data Reminder Cron",
  "nodes": [
    {
      "parameters": {
        "rule": {
          "interval": [
            {
              "field": "cronExpression",
              "expression": "0 * * * *"
            }
          ]
        }
      },
      "id": "wf7-trigger",
      "name": "Cron: Every Hour",
      "type": "n8n-nodes-base.cron",
      "typeVersion": 1,
      "position": [
        0,
        0
      ]
    },
    {
      "parameters": {
        "operation": "select",
        "table": "orders",
        "columns": "o.order_id, o.tx_ref, o.plan_code, o.channel_origin,\n                    o.expires_at,\n                    o.data_total_gb, o.data_remaining_gb,\n                    pa.platform, pa.platform_user_id, pa.display_name",
        "conditions": "o.status = 'fulfilled' AND o.expires_at IS NOT NULL AND o.expires_at BETWEEN NOW() AND NOW() + INTERVAL '7 days'",
        "options": {
          "join": "INNER JOIN platform_accounts pa ON pa.id = o.platform_account_id"
        }
      },
      "id": "wf7-expiring",
      "name": "Find Expiring Orders",
      "type": "n8n-nodes-base.postgres",
      "typeVersion": 1,
      "position": [
        200,
        -200
      ]
    },
    {
      "parameters": {
        "operation": "select",
        "table": "orders",
        "columns": "o.order_id, o.tx_ref, o.plan_code, o.channel_origin,\n                    o.data_total_gb, o.data_remaining_gb,\n                    pa.platform, pa.platform_user_id, pa.display_name",
        "conditions": "o.status = 'fulfilled' AND o.data_total_gb IS NOT NULL AND o.data_remaining_gb IS NOT NULL AND (o.data_total_gb - o.data_remaining_gb) / o.data_total_gb >= 0.8",
        "options": {
          "join": "INNER JOIN platform_accounts pa ON pa.id = o.platform_account_id"
        }
      },
      "id": "wf7-high-usage",
      "name": "Find High Data Usage",
      "type": "n8n-nodes-base.postgres",
      "typeVersion": 1,
      "position": [
        200,
        200
      ]
    },
    {
      "parameters": {
        "functionCode": "// Merge expiring and high-usage into deduplicated list\nconst inputs = $input.all();\nconst seen = new Set();\nconst combined = [];\n\nfor (const item of inputs) {\n    const order = item.json;\n    if (!seen.has(order.order_id)) {\n        seen.add(order.order_id);\n        order.reminder_type = [];\n\n        // Expiry warning\n        if (order.expires_at) {\n            order.reminder_type.push('expiry');\n            const daysLeft = Math.ceil((new Date(order.expires_at) - new Date()) / (24*60*60*1000));\n            order.message = `\u26a0\ufe0f Your ${order.plan_code || order.channel_origin} proxy expires in ${daysLeft} day${daysLeft === 1 ? '' : 's'}. Reply RENEW to keep access.`;\n        }\n\n        // Data usage warning\n        if (order.data_total_gb && order.data_remaining_gb) {\n            const used = parseFloat(order.data_total_gb) - parseFloat(order.data_remaining_gb);\n            const pct = Math.round((used / parseFloat(order.data_total_gb)) * 100);\n            order.data_pct = pct;\n            if (!order.message) {\n                order.message = `\ud83d\udcca You've used ${pct}% of your ${order.plan_code || order.channel_origin} data (${used.toFixed(1)}/${order.data_total_gb}GB). Reply UPGRADE for more.`;\n            }\n        }\n\n        combined.push({ json: order });\n    }\n}\nreturn combined;"
      },
      "id": "wf7-merge",
      "name": "Merge + Deduplicate",
      "type": "n8n-nodes-base.function",
      "typeVersion": 1,
      "position": [
        400,
        0
      ]
    },
    {
      "parameters": {
        "message": "{{ $json.message }}\n\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\nOrder: {{ $json.tx_ref || $json.order_id }}\nProduct: {{ $json.plan_code || $json.channel_origin }}\n{{#if $json.expires_at }}Expires: {{ $json.expires_at }}\n{{/if}}{{#if $json.data_pct }}Data: {{ $json.data_pct }}% used\n{{/if}}"
      },
      "id": "wf7-send",
      "name": "Send Reminder",
      "type": "n8n-nodes-base.whatsApp",
      "typeVersion": 1,
      "position": [
        600,
        0
      ]
    }
  ],
  "connections": {
    "Cron: Every Hour": {
      "main": [
        [
          {
            "node": "Find Expiring Orders",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Find High Data Usage",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Find Expiring Orders": {
      "main": [
        [
          {
            "node": "Merge + Deduplicate",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Find High Data Usage": {
      "main": [
        [
          {
            "node": "Merge + Deduplicate",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Merge + Deduplicate": {
      "main": [
        [
          {
            "node": "Send Reminder",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  },
  "settings": {
    "executionOrder": "v1",
    "saveManualExecutions": false,
    "timezone": "Africa/Lagos"
  },
  "staticData": null,
  "tags": [
    "reminder",
    "cron",
    "customer"
  ]
}
Pro

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

About this workflow

Expiry + Data Reminder Cron. Uses postgres, whatsApp. Scheduled trigger; 5 nodes.

Source: https://github.com/sonnyagent30-beep/bunche/blob/e991131928c348097e3fb411d5caa3b0466900f8/.n8n/workflows/expiry-reminder-cron.json — original creator credit. Request a take-down →

More Slack & Telegram workflows → · Browse all categories →

Related workflows

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

Slack & Telegram

Daily Summary. Uses postgres, whatsApp. Scheduled trigger; 12 nodes.

Postgres, WhatsApp
Slack & Telegram

Daily Summary. Uses postgres, whatsApp. Scheduled trigger; 12 nodes.

Postgres, WhatsApp
Slack & Telegram

EduPrime - Daily Management Report. Uses postgres, whatsApp, slack, emailSend. Scheduled trigger; 8 nodes.

Postgres, WhatsApp, Slack +1
Slack & Telegram

EduPrime - Daily Fee Reminders. Uses postgres, whatsApp. Scheduled trigger; 8 nodes.

Postgres, WhatsApp
Slack & Telegram

Trial Reset Daily Midnight. Uses postgres, whatsApp. Scheduled trigger; 6 nodes.

Postgres, WhatsApp