/n8n-tutorials

How to use static data in n8n?

Learn how to use static data in n8n to store and reuse constants, configurations, and predefined values across workflows using Set, JSON, environment variables, and more.

Matt Graham, CEO of Rapid Developers

Book a call with an Expert

Starting a new venture? Need to upgrade your web app? RapidDev builds application with your growth in mind.

Book a free consultation

How to use static data in n8n?

Static data in n8n allows you to store and reuse predefined values across workflows without fetching them from external sources. This is useful for constants, configuration settings, or any data that doesn't change frequently. You can leverage static data through n8n's Set node, JSON node, or by creating dedicated workflows that serve as data repositories.

 

Step 1: Understanding Static Data in n8n

 

Static data in n8n refers to fixed information that doesn't change during workflow execution. There are several approaches to use static data in your workflows:

Common methods for working with static data:

  • Using the Set node to define static values
  • Creating JSON objects with predefined data
  • Using environment variables for configuration
  • Creating dedicated workflows as data sources
  • Using the Function node to return static values

 

Step 2: Using the Set Node for Static Data

 

The Set node is one of the simplest ways to define static data in n8n.

  1. Add a Set node to your workflow.
  2. Define your static data as key-value pairs.
  3. Configure whether to keep or remove source data.

Here's how to set up a Set node with static data:


// Example of static data structure in Set node
{
  "apiKey": "YOUR_API_KEY\_HERE",
  "baseUrl": "https://api.example.com",
  "defaultParams": {
    "format": "json",
    "limit": 100
  },
  "userConfig": {
    "language": "en",
    "timezone": "UTC"
  }
}

 

Step 3: Creating JSON Data Objects

 

For more complex static data structures, you can use the JSON node:

  1. Add a JSON node to your workflow.
  2. Define your static JSON data in the "JSON" field.
  3. Access this data in subsequent nodes.

Example JSON node configuration:


{
  "products": [
    {
      "id": 1,
      "name": "Product A",
      "price": 29.99,
      "categories": ["electronics", "accessories"]
    },
    {
      "id": 2,
      "name": "Product B",
      "price": 49.99,
      "categories": ["electronics", "gadgets"]
    }
  ],
  "taxRates": {
    "standard": 0.20,
    "reduced": 0.10,
    "zero": 0.00
  },
  "shippingOptions": [
    {"name": "Standard", "price": 5.99, "days": "3-5"},
    {"name": "Express", "price": 12.99, "days": "1-2"}
  ]
}

 

Step 4: Using Environment Variables

 

For sensitive or configuration data, environment variables are ideal:

  1. Define environment variables in your n8n setup.
  2. Access them in your workflow using expressions.

To access environment variables in n8n:


// In a Function node or Expression field
const apiKey = $env.API\_KEY;
const databaseUrl = $env.DATABASE\_URL;

// Example usage in a Function node
return {
  json: {
    config: {
      apiKey: $env.API\_KEY,
      endpoint: $env.API\_ENDPOINT,
      timeout: parseInt($env.TIMEOUT) || 30000
    }
  }
}

 

Step 5: Creating a Data Repository Workflow

 

For more complex scenarios, you can create a dedicated workflow that serves as a data repository:

  1. Create a new workflow dedicated to storing static data.
  2. Use a Start node and a Set or JSON node to define your data.
  3. Add a Respond to Webhook node to return the data.
  4. In your main workflow, use the HTTP Request node to fetch this data.

Example of a data repository workflow:

  1. Start node
  2. Set node with your static data
  3. Respond to Webhook node configured to return the data

 

Step 6: Using the Function Node for Static Data

 

The Function node allows you to create and return static data programmatically:


// Function node code for static data
return {
  json: {
    companyInfo: {
      name: "ACME Corporation",
      founded: 1985,
      headquarters: "New York, NY",
      employees: 1250
    },
    contactDetails: {
      phone: "+1-555-123-4567",
      email: "[email protected]",
      address: "123 Business Ave, Suite 100"
    },
    departments: [
      {id: "sales", head: "Jane Smith", employees: 45},
      {id: "engineering", head: "John Doe", employees: 78},
      {id: "marketing", head: "Bob Johnson", employees: 34}
    ]
  }
}

 

Step 7: Using Code Snippets for Data Generation

 

For more dynamic static data (like dates, IDs, etc.), you can use code:


// Generate static data with some dynamic elements
return {
  json: {
    // Static elements
    apiVersion: "1.2.0",
    supportedFormats: ["json", "xml", "csv"],
    
    // Semi-dynamic elements
    generatedOn: new Date().toISOString(),
    fiscalYear: new Date().getFullYear(),
    
    // Programmatically generated array
    monthlyQuotas: Array.from({length: 12}, (\_, i) => ({
      month: i + 1,
      quota: 10000 + (i \* 500),
      bonusThreshold: 15000 + (i \* 750)
    }))
  }
}

 

Step 8: Accessing Static Data in Other Nodes

 

After defining static data, you need to know how to access it:

  1. Using dot notation in expressions: {{ $node["Set"].json.apiKey }}
  2. Using array notation for multiple items: {{ $node["JSON"].json.products[0].name }}
  3. Accessing environment variables: {{ $env.DATABASE\_URL }}

Example of accessing nested static data in an HTTP Request node:


// URL field of an HTTP Request node
{{ $node["Set"].json.baseUrl }}/api/{{ $node["Set"].json.version }}/products

// Headers
{
  "Authorization": "Bearer {{ $node["Set"].json.apiKey }}",
  "Content-Type": "application/json"
}

// Query Parameters
{
  "limit": {{ $node["Set"].json.defaultParams.limit }},
  "format": "{{ $node["Set"].json.defaultParams.format }}"
}

 

Step 9: Combining Static and Dynamic Data

 

Often, you'll need to combine static data with dynamic inputs:


// Function node example
const staticConfig = {
  taxRates: {
    US: 0.07,
    UK: 0.20,
    DE: 0.19
  },
  shippingRates: {
    domestic: 5.99,
    international: 15.99
  }
};

// Get dynamic data from input
const items = $input.json.items || [];
const country = $input.json.country || 'US';

// Calculate totals using static and dynamic data
const subtotal = items.reduce((sum, item) => sum + (item.price \* item.quantity), 0);
const taxRate = staticConfig.taxRates[country] || 0;
const taxAmount = subtotal \* taxRate;
const shippingCost = country === 'US' ? staticConfig.shippingRates.domestic : staticConfig.shippingRates.international;
const total = subtotal + taxAmount + shippingCost;

// Return combined data
return {
  json: {
    orderSummary: {
      subtotal,
      taxRate,
      taxAmount,
      shippingCost,
      total
    },
    processingDetails: {
      timestamp: new Date().toISOString(),
      countryCode: country,
      itemCount: items.length
    }
  }
}

 

Step 10: Managing and Updating Static Data

 

Static data may need updates occasionally. Here are strategies for managing updates:

  1. For Set and JSON nodes, update the values directly in the node.
  2. For environment variables, update them at the system or container level.
  3. For data repository workflows, update the central workflow.

Consider creating a version control system for your static data:


// Static data with versioning
return {
  json: {
    \_meta: {
      version: "2.0.3",
      lastUpdated: "2023-08-15T14:30:00Z",
      updatedBy: "admin"
    },
    configuration: {
      // Your actual configuration here
      apiEndpoints: {
        production: "https://api.example.com/v2",
        staging: "https://staging-api.example.com/v2",
        development: "https://dev-api.example.com/v2"
      },
      // Other configuration...
    }
  }
}

 

Step 11: Using Static Data for Conditional Logic

 

Static data is useful for making workflow decisions:


// Function node with conditional logic based on static data
const featureFlags = {
  enableNewUI: true,
  enableBetaFeatures: false,
  logLevel: "warning",
  maxRetries: 3,
  allowedCountries: ["US", "CA", "UK", "AU", "DE", "FR"]
};

// Get user data from input
const userData = $input.json;
const userCountry = userData.country;

// Apply business logic based on static configuration
if (!featureFlags.allowedCountries.includes(userCountry)) {
  return {
    json: {
      status: "error",
      message: "Service not available in your country",
      code: "COUNTRY\_RESTRICTED"
    }
  };
}

// Check if user can access beta features
const canAccessBeta = featureFlags.enableBetaFeatures || userData.userType === "premium";

return {
  json: {
    status: "success",
    uiVersion: featureFlags.enableNewUI ? "new" : "classic",
    betaAccess: canAccessBeta,
    maxRetries: featureFlags.maxRetries,
    // Other processed data...
  }
}

 

Step 12: Creating Reusable Data Templates

 

For complex applications, create reusable data templates:


// Function node with reusable templates
const templates = {
  emailNotification: {
    subject: "New notification from {{company}}",
    body: "Hello {{name}},\n\nYou have received a new {{type}} notification.\n\nRegards,\nThe {{company}} Team",
    footer: "© {{year}} {{company}}. All rights reserved."
  },
  apiResponse: {
    success: {
      status: "success",
      code: 200,
      data: null
    },
    error: {
      status: "error",
      code: 400,
      message: "An error occurred",
      details: null
    }
  }
};

// Function to fill template variables
function fillTemplate(template, variables) {
  let result = JSON.parse(JSON.stringify(template)); // Deep clone
  
  const replaceInString = (str, vars) => {
    return str.replace(/{{([^}]+)}}/g, (match, key) => {
      return vars[key.trim()] !== undefined ? vars[key.trim()] : match;
    });
  };
  
  // Recursive function to replace in all string properties
  const processObject = (obj, vars) => {
    for (const key in obj) {
      if (typeof obj[key] === 'string') {
        obj[key] = replaceInString(obj[key], vars);
      } else if (typeof obj[key] === 'object' && obj[key] !== null) {
        processObject(obj[key], vars);
      }
    }
    return obj;
  };
  
  return processObject(result, variables);
}

// Use the template with specific data
const companyInfo = {
  company: "ACME Inc",
  year: new Date().getFullYear()
};

const userData = $input.json;

// Create a customized email notification
const emailData = fillTemplate(templates.emailNotification, {
  ...companyInfo,
  name: userData.fullName,
  type: "account update"
});

// Create a customized API response
const apiResponse = fillTemplate(templates.apiResponse.success, {});
apiResponse.data = userData.results;

return {
  json: {
    email: emailData,
    response: apiResponse
  }
}

 

Step 13: Advanced Data Organization with Namespaces

 

For large applications, organize static data with namespaces:


// Organized static data with namespaces
return {
  json: {
    system: {
      version: "3.2.1",
      environment: "production",
      maintenanceMode: false,
      limits: {
        requestsPerMinute: 60,
        maxUploadSize: 10485760
      }
    },
    ui: {
      theme: "light",
      dateFormat: "YYYY-MM-DD",
      timeFormat: "24h",
      decimalSeparator: ".",
      thousandsSeparator: ","
    },
    pricing: {
      currency: "USD",
      plans: {
        basic: {price: 9.99, features: ["feature1", "feature2"]},
        pro: {price: 19.99, features: ["feature1", "feature2", "feature3"]},
        enterprise: {price: 49.99, features: ["feature1", "feature2", "feature3", "feature4"]}
      },
      discounts: {
        annual: 0.15,
        educational: 0.50,
        nonprofit: 0.30
      }
    },
    locations: {
      headquarters: {
        address: "123 Main St",
        city: "New York",
        country: "USA"
      },
      datacenters: [
        {region: "us-east", location: "Virginia", status: "active"},
        {region: "eu-west", location: "Ireland", status: "active"},
        {region: "ap-south", location: "Singapore", status: "maintenance"}
      ]
    }
  }
}

 

Step 14: Making Static Data More Readable

 

For better maintainability, format complex static data:


// Well-structured static data example
return {
  json: {
    // API Configuration
    api: {
      // Base URLs for different environments
      baseUrls: {
        development: "https://dev-api.example.com/v1",
        staging: "https://staging-api.example.com/v1",
        production: "https://api.example.com/v1"
      },
      
      // Default request options
      defaults: {
        timeout: 30000,
        retries: 3,
        headers: {
          "Content-Type": "application/json",
          "Accept": "application/json"
        }
      },
      
      // Rate limiting settings
      rateLimits: {
        requestsPerMinute: 60,
        burstRequests: 10,
        cooldownPeriod: 60000
      }
    },
    
    // Business rules
    businessRules: {
      // Order processing rules
      orders: {
        minimumOrderValue: 10.00,
        freeShippingThreshold: 50.00,
        
        // Tax rates by region
        taxRates: {
          domestic: 0.07,
          international: {
            EU: 0.21,
            UK: 0.20,
            CA: 0.13,
            // Other regions...
          }
        },
        
        // Shipping costs
        shipping: {
          domestic: {
            standard: 4.99,
            express: 12.99
          },
          international: {
            standard: 14.99,
            express: 24.99
          }
        }
      },
      
      // User account rules
      accounts: {
        passwordMinLength: 8,
        passwordRequirements: ["uppercase", "lowercase", "number", "special"],
        sessionTimeout: 3600,
        maxLoginAttempts: 5
      }
    },
    
    // Content and localization
    content: {
      // Company information
      company: {
        name: "ACME Corporation",
        slogan: "Building the Future Today",
        founded: 1985,
        logo: {
          light: "https://assets.example.com/logo-light.png",
          dark: "https://assets.example.com/logo-dark.png"
        }
      },
      
      // Error messages
      errors: {
        general: "An unexpected error occurred. Please try again later.",
        notFound: "The requested resource was not found.",
        accessDenied: "You don't have permission to access this resource.",
        validation: "Please check your input and try again."
      }
    }
  }
}

 

Step 15: Practical Example - E-commerce Configuration

 

Let's put it all together with a practical e-commerce example:


// E-commerce static configuration
const storeConfig = {
  // Store information
  store: {
    name: "TechGadgets",
    domain: "techgadgets.example",
    supportEmail: "[email protected]",
    phoneNumber: "+1-555-123-4567",
    socialMedia: {
      facebook: "https://facebook.com/techgadgets",
      twitter: "https://twitter.com/techgadgets",
      instagram: "https://instagram.com/techgadgets"
    }
  },
  
  // Product categories with display settings
  categories: [
    {id: "smartphones", name: "Smartphones", featured: true, icon: "phone"},
    {id: "laptops", name: "Laptops & Computers", featured: true, icon: "laptop"},
    {id: "accessories", name: "Accessories", featured: false, icon: "headphones"},
    {id: "wearables", name: "Wearable Tech", featured: true, icon: "watch"},
    {id: "cameras", name: "Cameras", featured: false, icon: "camera"},
    {id: "audio", name: "Audio", featured: false, icon: "speaker"}
  ],
  
  // Payment options
  paymentMethods: [
    {id: "credit", name: "Credit Card", enabled: true, fee: 0},
    {id: "paypal", name: "PayPal", enabled: true, fee: 0},
    {id: "bank", name: "Bank Transfer", enabled: true, fee: 0},
    {id: "crypto", name: "Cryptocurrency", enabled: false, fee: 0.01}
  ],
  
  // Shipping options
  shipping: {
    methods: [
      {id: "standard", name: "Standard Shipping", days: "3-5", base: 4.99},
      {id: "express", name: "Express Shipping", days: "1-2", base: 12.99},
      {id: "overnight", name: "Overnight", days: "Next day", base: 24.99}
    ],
    freeThreshold: 75,
    weightMultiplier: 0.5,  // Additional cost per kg
    internationalMultiplier: 2.5  // Multiplier for international shipping
  },
  
  // Tax configuration
  taxes: {
    default: 0.07,  // 7% default tax rate
    byRegion: {
      "US-CA": 0.0725,  // California
      "US-NY": 0.0845,  // New York
      "US-TX": 0.0625,  // Texas
      "CA": 0.13,       // Canada
      "EU": 0.21,       // European Union
      "UK": 0.20,       // United Kingdom
      "AU": 0.10        // Australia
    },
    exemptCategories: ["books", "food", "medicine"]
  },
  
  // Discount rules
  discounts: {
    volumeDiscounts: [
      {threshold: 3, discount: 0.05},  // 5% off for 3+ items
      {threshold: 5, discount: 0.10},  // 10% off for 5+ items
      {threshold: 10, discount: 0.15}  // 15% off for 10+ items
    ],
    promoCode: {
      "WELCOME10": {discount: 0.10, expiry: "2023-12-31", oneTime: true},
      "SUMMER2023": {discount: 0.15, expiry: "2023-08-31", oneTime: false},
      "LOYALTY5": {discount: 0.05, expiry: null, oneTime: false}
    },
    stackable: false  // Whether multiple discounts can be combined
  },
  
  // Email templates
  emailTemplates: {
    orderConfirmation: {
      subject: "Your TechGadgets Order #{{orderNumber}}",
      template: "order-confirmation"
    },
    shipping: {
      subject: "Your TechGadgets Order #{{orderNumber}} Has Shipped",
      template: "order-shipped"
    },
    abandoned: {
      subject: "Complete Your TechGadgets Purchase",
      template: "cart-abandoned"
    }
  },
  
  // Feature flags
  features: {
    reviews: true,
    wishlist: true,
    comparison: true,
    recentlyViewed: true,
    recommendations: true,
    giftWrapping: false,
    subscriptions: false
  }
};

// Process order with the static configuration
function processOrder(order) {
  // Get shipping cost
  let shippingMethod = storeConfig.shipping.methods.find(m => m.id === order.shippingMethodId);
  let shippingCost = shippingMethod ? shippingMethod.base : storeConfig.shipping.methods[0].base;
  
  // Add weight-based cost
  if (order.weight > 1) {
    shippingCost += (order.weight - 1) \* storeConfig.shipping.weightMultiplier;
  }
  
  // Apply international multiplier if needed
  if (order.country !== 'US') {
    shippingCost \*= storeConfig.shipping.internationalMultiplier;
  }
  
  // Apply free shipping if order value exceeds threshold
  if (order.subtotal >= storeConfig.shipping.freeThreshold) {
    shippingCost = 0;
  }
  
  // Calculate tax
  let taxRate = storeConfig.taxes.default;
  const regionKey = order.country === 'US' ? `US-${order.state}` : order.country;
  
  if (storeConfig.taxes.byRegion[regionKey]) {
    taxRate = storeConfig.taxes.byRegion[regionKey];
  }
  
  const taxAmount = order.subtotal \* taxRate;
  
  // Calculate discounts
  let discountAmount = 0;
  
  // Check promo code
  if (order.promoCode && storeConfig.discounts.promoCode[order.promoCode]) {
    const promo = storeConfig.discounts.promoCode[order.promoCode];
    const now = new Date();
    
    // Check if promo is valid
    if (!promo.expiry || new Date(promo.expiry) > now) {
      discountAmount = order.subtotal \* promo.discount;
    }
  }
  
  // Check volume discounts
  if (order.itemCount >= 3) {
    const volumeDiscount = storeConfig.discounts.volumeDiscounts
      .filter(vd => vd.threshold <= order.itemCount)
      .sort((a, b) => b.threshold - a.threshold)[0];
    
    if (volumeDiscount) {
      // Only apply if better than promo code or if stackable
      const potentialVolumeDiscount = order.subtotal \* volumeDiscount.discount;
      
      if (storeConfig.discounts.stackable) {
        discountAmount += potentialVolumeDiscount;
      } else if (potentialVolumeDiscount > discountAmount) {
        discountAmount = potentialVolumeDiscount;
      }
    }
  }
  
  // Calculate total
  const total = order.subtotal + shippingCost + taxAmount - discountAmount;
  
  return {
    orderSummary: {
      subtotal: order.subtotal,
      shipping: shippingCost,
      tax: taxAmount,
      discount: discountAmount,
      total: total
    },
    shippingDetails: {
      method: shippingMethod.name,
      estimatedDelivery: shippingMethod.days,
      trackingAvailable: order.shippingMethodId !== 'standard'
    },
    paymentDetails: {
      method: storeConfig.paymentMethods.find(m => m.id === order.paymentMethodId).name
    },
    storeInfo: {
      name: storeConfig.store.name,
      supportEmail: storeConfig.store.supportEmail,
      supportPhone: storeConfig.store.phoneNumber
    }
  };
}

// Example usage with an incoming order
const incomingOrder = $input.json;
return {
  json: processOrder(incomingOrder)
}

 

Conclusion

 

Static data in n8n provides a powerful way to manage configuration settings, business rules, and constants across your workflows. By using the techniques outlined in this guide—from simple Set nodes to complex data templates and namespaces—you can create more maintainable, configurable, and robust automation workflows. Remember to consider how your static data will be maintained and updated over time, and choose the appropriate approach based on your specific needs.

Want to explore opportunities to work with us?

Connect with our team to unlock the full potential of no-code solutions with a no-commitment consultation!

Book a Free Consultation

Client trust and success are our top priorities

When it comes to serving you, we sweat the little things. That’s why our work makes a big impact.

Rapid Dev was an exceptional project management organization and the best development collaborators I've had the pleasure of working with. They do complex work on extremely fast timelines and effectively manage the testing and pre-launch process to deliver the best possible product. I'm extremely impressed with their execution ability.

CPO, Praction - Arkady Sokolov

May 2, 2023

Working with Matt was comparable to having another co-founder on the team, but without the commitment or cost. He has a strategic mindset and willing to change the scope of the project in real time based on the needs of the client. A true strategic thought partner!

Co-Founder, Arc - Donald Muir

Dec 27, 2022

Rapid Dev are 10/10, excellent communicators - the best I've ever encountered in the tech dev space. They always go the extra mile, they genuinely care, they respond quickly, they're flexible, adaptable and their enthusiasm is amazing.

Co-CEO, Grantify - Mat Westergreen-Thorne

Oct 15, 2022

Rapid Dev is an excellent developer for no-code and low-code solutions.
We’ve had great success since launching the platform in November 2023. In a few months, we’ve gained over 1,000 new active users. We’ve also secured several dozen bookings on the platform and seen about 70% new user month-over-month growth since the launch.

Co-Founder, Church Real Estate Marketplace - Emmanuel Brown

May 1, 2024 

Matt’s dedication to executing our vision and his commitment to the project deadline were impressive. 
This was such a specific project, and Matt really delivered. We worked with a really fast turnaround, and he always delivered. The site was a perfect prop for us!

Production Manager, Media Production Company - Samantha Fekete

Sep 23, 2022