diff --git a/packages/loot-core/src/server/budget/goal-template.pegjs b/packages/loot-core/src/server/budget/goal-template.pegjs
index ab365d6200e263959bb6e7f8b0e08bd6ca32b363..164602a5126e8a2aabee302c65c584578ca8d4fd 100644
--- a/packages/loot-core/src/server/budget/goal-template.pegjs
+++ b/packages/loot-core/src/server/budget/goal-template.pegjs
@@ -1,24 +1,25 @@
 // https://peggyjs.org
 
 expr
-  = percent: percent _ of _ category: $([^\r\n\t]+)
-    { return { type: 'percentage', percent: +percent, category } }
-  / amount: amount _ repeatEvery _ weeks: weekCount _ starting _ starting: date limit: limit?
-    { return { type: 'week', amount, weeks, starting, limit } }
-  / amount: amount _ by _ month: month from: spendFrom? repeat: (_ repeatEvery _ repeat)?
+  = priority: priority? _? percent: percent _ of _ category: name
+    { return { type: 'percentage', percent: +percent, category, priority: +priority }}
+  / priority: priority? _? amount: amount _ repeatEvery _ weeks: weekCount _ starting _ starting: date limit: limit?
+    { return { type: 'week', amount, weeks, starting, limit, priority: +priority }}
+  / priority: priority? _? amount: amount _ by _ month: month from: spendFrom? repeat: (_ repeatEvery _ repeat)?
     { return {
       type: from ? 'spend' : 'by',
       amount,
       month,
       ...(repeat ? repeat[3] : {}),
-      from
+      from,
+      priority: +priority
     } }
-  / monthly: amount limit: limit?
-    { return { type: 'simple', monthly, limit } }
-  / upTo _ limit: amount
-    { return { type: 'simple', limit } }
-  / schedule _ name: name
-  	{ return { type: 'schedule', name} }
+  / priority: priority? _? monthly: amount limit: limit?
+    { return { type: 'simple', monthly, limit, priority: +priority  } }
+  / priority: priority? _? upTo _ limit: amount
+    { return { type: 'simple', limit , priority: +priority } }
+  / priority: priority? _? schedule _ name: name
+    { return { type: 'schedule', name, priority: +priority } }
 
 repeat 'repeat interval'
   = 'month'i { return { annual: false } }
@@ -42,6 +43,7 @@ repeatEvery = 'repeat'i _ 'every'i
 starting = 'starting'i
 upTo = 'up'i _ 'to'i
 schedule = 'schedule'i
+priority = '-'i number: number _ {return number}
 
 _ 'space' = ' '+
 d 'digit' = [0-9]
diff --git a/packages/loot-core/src/server/budget/goaltemplates.ts b/packages/loot-core/src/server/budget/goaltemplates.ts
index 285915fe3897650df5c4694a464010e9d78bf6c0..805e4ad16018673480033ff3046c83e323c23cb1 100644
--- a/packages/loot-core/src/server/budget/goaltemplates.ts
+++ b/packages/loot-core/src/server/budget/goaltemplates.ts
@@ -26,54 +26,141 @@ export function overwriteTemplate({ month }) {
   return processTemplate(month, true);
 }
 
+function checkScheduleTemplates(template) {
+  let lowPriority = template[0].priority;
+  let errorNotice = false;
+  for (let l = 1; l < template.length; l++) {
+    if (template[l].priority !== lowPriority) {
+      lowPriority = Math.min(lowPriority, template[l].priority);
+      errorNotice = true;
+    }
+  }
+  return { lowPriority, errorNotice };
+}
+
 async function processTemplate(month, force) {
-  let category_templates = await getCategoryTemplates();
+  let num_applied = 0;
   let errors = [];
+  let category_templates = await getCategoryTemplates();
+  let lowestPriority = 0;
+  let originalCategoryBalance = [];
 
   let categories = await db.all(
     'SELECT * FROM v_categories WHERE tombstone = 0',
   );
 
-  let num_applied = 0;
+  //clears templated categories
   for (let c = 0; c < categories.length; c++) {
     let category = categories[c];
-
     let budgeted = await getSheetValue(
       monthUtils.sheetForMonth(month),
       `budget-${category.id}`,
     );
+    if (budgeted)
+      originalCategoryBalance.push({ cat: category, amount: budgeted });
+    let template = category_templates[category.id];
+    if (template) {
+      for (let l = 0; l < template.length; l++)
+        lowestPriority =
+          template[l].priority > lowestPriority
+            ? template[l].priority
+            : lowestPriority;
+      await setBudget({
+        category: category.id,
+        month,
+        amount: 0,
+      });
+    }
+  }
 
-    if (budgeted === 0 || force) {
+  for (let priority = 0; priority <= lowestPriority; priority++) {
+    for (let c = 0; c < categories.length; c++) {
+      let category = categories[c];
       let template = category_templates[category.id];
-
       if (template) {
-        errors = errors.concat(
-          template
-            .filter(t => t.type === 'error')
-            .map(({ line, error }) =>
-              [
-                category.name + ': ' + error.message,
-                line,
-                ' '.repeat(
-                  TEMPLATE_PREFIX.length + error.location.start.offset,
-                ) + '^',
-              ].join('\n'),
-            ),
-        );
-        let { amount: to_budget, errors: applyErrors } =
-          await applyCategoryTemplate(category, template, month, force);
-        if (to_budget != null) {
-          num_applied++;
-          await setBudget({ category: category.id, month, amount: to_budget });
-        }
-        if (applyErrors != null) {
-          errors = errors.concat(
-            applyErrors.map(error => `${category.name}: ${error}`),
+        //check that all schedule and by lines have the same priority level
+        let skipSchedule = false;
+        let isScheduleOrBy = false;
+        let priorityCheck = 0;
+        if (
+          template.filter(t => t.type === 'schedule' || t.type === 'by')
+            .length > 0
+        ) {
+          let { lowPriority, errorNotice } = await checkScheduleTemplates(
+            template,
           );
+          priorityCheck = lowPriority;
+          skipSchedule = priorityCheck !== priority ? true : false;
+          isScheduleOrBy = true;
+          if (!skipSchedule && errorNotice)
+            errors.push(
+              category.name +
+                ': Schedules and By templates should all have the same priority.  Using priority ' +
+                priorityCheck,
+            );
+        }
+        if (!skipSchedule) {
+          if (!isScheduleOrBy)
+            template = template.filter(t => t.priority === priority);
+          if (template.length > 0) {
+            errors = errors.concat(
+              template
+                .filter(t => t.type === 'error')
+                .map(({ line, error }) =>
+                  [
+                    category.name + ': ' + error.message,
+                    line,
+                    ' '.repeat(
+                      TEMPLATE_PREFIX.length + error.location.start.offset,
+                    ) + '^',
+                  ].join('\n'),
+                ),
+            );
+            let { amount: to_budget, errors: applyErrors } =
+              await applyCategoryTemplate(
+                category,
+                template,
+                month,
+                priority,
+                force,
+              );
+            if (to_budget != null) {
+              num_applied++;
+              await setBudget({
+                category: category.id,
+                month,
+                amount: to_budget,
+              });
+            }
+            if (applyErrors != null) {
+              errors = errors.concat(
+                applyErrors.map(error => `${category.name}: ${error}`),
+              );
+            }
+          }
         }
       }
     }
   }
+  if (!force) {
+    //if overwrite is not preferred, set cell to original value
+    for (let l = 0; l < originalCategoryBalance.length; l++) {
+      await setBudget({
+        category: originalCategoryBalance[l].cat.id,
+        month,
+        amount: originalCategoryBalance[l].amount,
+      });
+      //if overwrite is not preferred, remove template errors for category
+      let j = errors.length;
+      for (let k = 0; k < j; k++) {
+        if (errors[k].includes(originalCategoryBalance[l].cat.name)) {
+          errors.splice(k, 1);
+          j--;
+        }
+      }
+    }
+  }
+
   if (num_applied === 0) {
     if (errors.length) {
       return {
@@ -104,8 +191,7 @@ async function processTemplate(month, force) {
   }
 }
 
-const TEMPLATE_PREFIX = '#template ';
-
+const TEMPLATE_PREFIX = '#template';
 async function getCategoryTemplates() {
   let templates = {};
 
@@ -134,7 +220,13 @@ async function getCategoryTemplates() {
   return templates;
 }
 
-async function applyCategoryTemplate(category, template_lines, month, force) {
+async function applyCategoryTemplate(
+  category,
+  template_lines,
+  month,
+  priority,
+  force,
+) {
   let current_month = new Date(`${month}-01`);
   let errors = [];
   let all_schedule_names = await db.all(
@@ -200,12 +292,13 @@ async function applyCategoryTemplate(category, template_lines, month, force) {
     });
   }
 
-  let to_budget = 0;
-  let limit;
   let sheetName = monthUtils.sheetForMonth(month);
   let budgeted = await getSheetValue(sheetName, `budget-${category.id}`);
   let spent = await getSheetValue(sheetName, `sum-amount-${category.id}`);
   let balance = await getSheetValue(sheetName, `leftover-${category.id}`);
+  let budgetAvailable = await getSheetValue(sheetName, `to-budget`);
+  let to_budget = budgeted;
+  let limit;
   let last_month_balance = balance - spent - budgeted;
   let totalTarget = 0;
   let totalMonths = 0;
@@ -223,11 +316,18 @@ async function applyCategoryTemplate(category, template_lines, month, force) {
             limit = amountToInteger(template.limit);
           }
         }
+        let increment = 0;
         if (template.monthly != null) {
           let monthly = amountToInteger(template.monthly);
-          to_budget += monthly;
+          increment = monthly;
+        } else {
+          increment = limit;
+        }
+        if (to_budget + increment < budgetAvailable || !priority) {
+          to_budget += increment;
         } else {
-          to_budget += limit;
+          if (budgetAvailable > 0) to_budget += budgetAvailable;
+          errors.push(`Insufficient funds.`);
         }
         break;
       }
@@ -259,10 +359,16 @@ async function applyCategoryTemplate(category, template_lines, month, force) {
 
         let diff = totalTarget - last_month_balance;
         if (diff >= 0 && totalMonths > 0 && l === N - 1) {
-          to_budget += Math.round(
+          let increment = Math.round(
             ((totalTarget - last_month_balance) / totalMonths) *
               (N - skipMonths),
           );
+          if (to_budget + increment < budgetAvailable || !priority) {
+            to_budget += increment;
+          } else {
+            if (budgetAvailable > 0) to_budget += budgetAvailable;
+            errors.push(`Insufficient funds.`);
+          }
         }
         break;
       }
@@ -284,9 +390,14 @@ async function applyCategoryTemplate(category, template_lines, month, force) {
 
         while (w.getTime() < next_month.getTime()) {
           if (w.getTime() >= current_month.getTime()) {
-            to_budget += amount;
+            if (to_budget + amount < budgetAvailable || !priority) {
+              to_budget += amount;
+            } else {
+              if (budgetAvailable > 0) to_budget += budgetAvailable;
+              errors.push(`Insufficient funds.`);
+            }
+            w = addWeeks(w, weeks);
           }
-          w = addWeeks(w, weeks);
         }
         break;
       }
@@ -324,16 +435,24 @@ async function applyCategoryTemplate(category, template_lines, month, force) {
         }
         let num_months = differenceInCalendarMonths(to_month, current_month);
         let target = amountToInteger(template.amount);
+
+        let increment = 0;
         if (num_months < 0) {
           errors.push(`${template.month} is in the past.`);
           return { errors };
         } else if (num_months === 0) {
-          to_budget = target - already_budgeted;
+          increment = target - already_budgeted;
         } else {
-          to_budget = Math.round(
+          increment = Math.round(
             (target - already_budgeted) / (num_months + 1),
           );
         }
+        if (increment < budgetAvailable || !priority) {
+          to_budget = increment;
+        } else {
+          if (budgetAvailable > 0) to_budget = budgetAvailable;
+          errors.push(`Insufficient funds.`);
+        }
         break;
       }
       case 'percentage': {
@@ -356,7 +475,16 @@ async function applyCategoryTemplate(category, template_lines, month, force) {
             `sum-amount-${income_category.id}`,
           );
         }
-        to_budget = Math.max(0, Math.round(monthlyIncome * (percent / 100)));
+        let increment = Math.max(
+          0,
+          Math.round(monthlyIncome * (percent / 100)),
+        );
+        if (increment < budgetAvailable || !priority) {
+          to_budget = increment;
+        } else {
+          if (budgetAvailable > 0) to_budget = budgetAvailable;
+          errors.push(`Insufficient funds.`);
+        }
         break;
       }
       case 'error':
@@ -406,7 +534,13 @@ async function applyCategoryTemplate(category, template_lines, month, force) {
           } else {
             monthly_target = target;
           }
-          to_budget += monthly_target - balance + budgeted;
+          let increment = monthly_target - balance + budgeted;
+          if (to_budget + increment < budgetAvailable || !priority) {
+            to_budget += increment;
+          } else {
+            if (budgetAvailable > 0) to_budget = budgetAvailable;
+            errors.push(`Insufficient funds.`);
+          }
         }
         break;
       }
@@ -418,14 +552,13 @@ async function applyCategoryTemplate(category, template_lines, month, force) {
       to_budget = limit - last_month_balance;
     }
   }
-
   if (
     ((category.budgeted != null && category.budgeted !== 0) ||
       to_budget === 0) &&
     !force
   ) {
     return { errors };
-  } else if (category.budgeted === to_budget && force) {
+  } else if (category.budgeted === to_budget) {
     return null;
   } else {
     let str = category.name + ': ' + integerToAmount(last_month_balance);
diff --git a/upcoming-release-notes/961.md b/upcoming-release-notes/961.md
new file mode 100644
index 0000000000000000000000000000000000000000..622a90faa0de7e20894427bf4c5d4f0127b2c2a4
--- /dev/null
+++ b/upcoming-release-notes/961.md
@@ -0,0 +1,6 @@
+---
+category: Enhancements
+authors: [shall0pass, youngcw]
+---
+
+Goals: Add priority support
\ No newline at end of file