惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

IntelliJ IDEA : IntelliJ IDEA – the Leading IDE for Professional Development in Java and Kotlin | The JetBrains Blog
IntelliJ IDEA : IntelliJ IDEA – the Leading IDE for Professional Development in Java and Kotlin | The JetBrains Blog
G
GRAHAM CLULEY
P
Privacy & Cybersecurity Law Blog
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
宝玉的分享
宝玉的分享
P
Proofpoint News Feed
H
Help Net Security
V
Visual Studio Blog
阮一峰的网络日志
阮一峰的网络日志
C
Cisco Blogs
人人都是产品经理
人人都是产品经理
Know Your Adversary
Know Your Adversary
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
Recorded Future
Recorded Future
I
Intezer
罗磊的独立博客
T
The Exploit Database - CXSecurity.com
Blog — PlanetScale
Blog — PlanetScale
Malwarebytes
Malwarebytes
Spread Privacy
Spread Privacy
T
Tor Project blog
V
Vulnerabilities – Threatpost
云风的 BLOG
云风的 BLOG
腾讯CDC
B
Blog RSS Feed
Stack Overflow Blog
Stack Overflow Blog
F
Future of Privacy Forum
MyScale Blog
MyScale Blog
Latest news
Latest news
IT之家
IT之家
MongoDB | Blog
MongoDB | Blog
The Hacker News
The Hacker News
S
Securelist
博客园 - 【当耐特】
C
CXSECURITY Database RSS Feed - CXSecurity.com
T
Threat Research - Cisco Blogs
Jina AI
Jina AI
Cisco Talos Blog
Cisco Talos Blog
B
Blog
博客园 - 三生石上(FineUI控件)
Last Week in AI
Last Week in AI
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
M
MIT News - Artificial intelligence
V
V2EX
D
Darknet – Hacking Tools, Hacker News & Cyber Security
The Cloudflare Blog
The GitHub Blog
The GitHub Blog
博客园 - 聂微东
F
Full Disclosure
C
CERT Recently Published Vulnerability Notes

DEV Community

Beyond the Prompt: How to Build Stateful AI Agents with Persistent Memory and Self-Learning Loops Antigravity CLI: A Hands-On Guide to Google's Terminal Coding Agent Rethinking Geo-Blocking and Stripe's Failures in Global Access: A Cautionary Tale of Misoptimization I Built a Free Brat Generator - Here's What I Learned About Next.js Performance published Found a Second Layer to a GitHub Follow Botnet? AI Daily Digest: May 22, 2026 — Agentic Workflows, Coding Agents & Embodied AI How I Secured Internal Microservice Calls Without Passing JWTs Stop Mixing Them Up: SLI vs SLO vs SLA Explained Rebuilding My Engineering Mind Building a Music Production Ecosystem Instead of Just Releasing Plugins The Vonage Dev Discussion: How AI is transforming software development I Gave Our Enterprise AI a Memory. It Started Citing Last Quarter's Incidents. 𝐓𝐡𝐞 𝐂𝐨𝐦𝐦𝐮𝐧𝐢𝐜𝐚𝐭𝐢𝐨𝐧 𝐒𝐭𝐲𝐥𝐞 𝐂𝐫𝐢𝐬𝐢𝐬 Hermes Agent in the Wild: How I Turned It Into an AI Ops Employee Navigating the Hazy Jungle of Global E-commerce: How We Built a Reliable System for Digital Creators in Tanzania The Cost of Cross-Platform Development: Native Module Integration AI-Native Apps Will Swallow the Web I switched my Gemma 4 model three times in 72 hours. Here's the decision tree I wish I'd had. Inside #100DaysofSolana: A Guided Path into Web3 I Built and Shipped TinyHab: an ADHD-Friendly Habit Tracker for iOS I'm an ECE Student Who Vibe Codes Hardware Projects — Here's What Google I/O 2026 Actually Changed for Me From Fragmented Pipelines to Coherent Intelligence — Why Gemma 4 Actually Changes How I Work Our AI Inference Bill Dropped 65% After We Stopped Treating Every Query the Same Why P95 Latency Is the Only Metric That Matters at 3 AM Recycling made easy: a Polish recycling assistant powered by Gemma 4 The Complete Guide to Running a Midnight Node: Setup, Sync & Monitoring De CSRF a RCE: una visita web cuesta una shell en OpenYak Why We Built a Faster Wiki Building a Browser-Based Inkarnate Alternative for D&D Battle Maps Apache Kafka How to Build a FinTech Platform as a Solo Developer (By Any Means Necessary) Your LLM Logs Deserve Better — Send Claude Code Events to Bronto I built a free tool to track subscriptions and stop getting surprised by charges Building the TEYZIX CORE Internship Portal — My Full-Stack Development Journey PocketCFO: a private personal-finance brain that runs entirely in your browser Go Idioms I Wish I Knew Earlier Hey how are you guys I'm newbie web developer , learning wordpress+elementor Right now I don't know what to make I don't know what to write or use what color can you tell me about it ? Google I/O 2026 Blew My Mind — Here's What It Means for the Family App I'm Building 5 Things I Learned in My First Month as a Dev Intern EU AI Sovereignty Belongs in the Workflow Layer Why AI Coding Agents Need Business Context, Not Just Code Context How I Built 9 Claude AI Features into a Production SaaS Expo SDK 56 HashiCorp built an MCP server for writing Terraform. I built one for reviewing it Why Enterprise AI Agent Deployments Keep Failing Date Shear: A New Term for a Common Programming Pain Point Compass v1.1.0 · we shipped a memory plugin that catches its own consumption drift Zod Validation: Type-Safe APIs & Forms in TypeScript (Complete Guide) GitHub Actions CI/CD: Build a Complete Node.js Pipeline (2026) MCP in 2026: The numbers behind the ecosystem explosion working with an ai model mirror Learnt new things Four Metrics That Actually Tell You Whether Your Enterprise RAG Is Working Beyond the Stateless Prompt: Building an Auditable Product Intelligence Pipeline with Cascadeflow and Hindsight Most Creators Are Building in Pieces. I’m Building the Entire System. The Hidden Privacy Problem in Every AI App CVE-2026-26007: Subgroup Confinement Attack in pyca/cryptography The One Thing I See in Every Developer Who Gets Unstuck AI Memory Governance for Legal Tech: How Contract AI Agents Handle Privileged Data Two tables, zero migrations, full LINQ — a .NET data engine that's been running our production for 3 months Join the GitHub Finish-Up-A-Thon Challenge: $3,000 Prize Pool! I Replaced a $50/Month OCR API with Gemma 4’s Native Vision (And You Can Too) Building a Data-Driven Medical Image Enhancement Pipeline with Differential Evolution 🔥🩻 Why I Like Small Software Beyond the Model: Why the Gemini Ecosystem and Google AI Studio Are Redefining Enterprise AI Architecture in 2026 Complete set of Claude Skills for Solo Developer I read 50 years of network science, then built a CRM that runs entirely in the browser The New AI Workflow Is Not “More Agents” How to Make Large Time-Series Charts Smooth in Vue.js + ApexCharts (and fix Zoom & Scroll behavior issues) I Built a Cross-Platform Port Intelligence Tool to Stop Accidental Process Kills During Local Dev AI is heading toward a wall, and most people still don’t see it... Python String Methods Explained Simply (Common Operations) Why We Built a Zero-Knowledge Clipboard Manager for Developers (And Dropped Native Mobile Apps) Add Your Own Component to Bombie in 5 Edits Why Your OSS Advocacy Strategy Probably Doesn't Fit Building an MCP server for a Swiss hosting provider (and what reverse-engineering its manager taught me) Does MCP Still Matter in the AI Ecosystem? Building a Smart LRU Cache in Java: When Machines Mimic Human Memory 🧠💻 A Beginner’s Guide to Redux in React Build a Real-Time Excalidraw-like Collaborative Canvas using Velt MCP and Antigravity🎉 Using Reddit to Validate SaaS Ideas Before Building How We Built an AI That Evolves Alongside a Creator Through Memory Building a Self-Hosted AI WhatsApp Agent for Structured Invoice Extraction Three Design Decisions That Shaped the Enterprise RAG Retrieval Pipeline How React's Virtual DOM Works Under the Hood Build a Dropbox Paper-Style Collaborative Editor with Next.js and Velt💥 Holy Typos, Batman! How I Built 'SpellJump' How to Test Frontend Error States Without Breaking Your Backend A .NET Dinosaur in Web3. Day 8 — Reading & Writing — WishList Chain Building AI Digital Employees with Markus: An Open-Source Platform for Agent Teams [Boost] The Auditor — High-Reasoning Synthesis and the Ethics of Governance Building 'Offline Brain': How I Wrote My First Custom Agent Skill for Android (Google I/O 2026) 📱🧠 Building a Superhuman-Style Collaborative Email Editor with Next.js and Velt🔥 I Built an On-Chain Marketplace Where AI Agents Solve GitHub Bounties for USDC Three Stripe subscription patterns I locked in before going live (with code) Six Ways AI Agents Communicate in 2026. I Benchmarked All of Them. Building AI Digital Employees with Markus: An Open-Source AI Workforce Platform I built a tool that detects broken security headers, missing robots.txt, and WP_DEBUG=true — then opens a PR to fix them automatically NIST Just Exposed the Age Estimation Number Vendors Don't Want You to See
Shopify Functions vs Shopify Scripts: A Migration Walkthrough
Alex Massaad · 2026-05-22 · via DEV Community

We covered the Scripts deprecation in an earlier post. The short version: Shopify Scripts stop running on June 30, 2026, and Shopify Functions are the replacement. As of April 15, 2026, you can no longer edit or publish new Scripts, which means Plus merchants who haven't migrated yet are now in the danger zone.

This post is the next layer down. It's the walkthrough. What the actual migration looks like in code, what breaks in translation, and the order we run the work in when a client hands us a Script Editor full of Ruby and asks us to make it Functions.

If you have a developer on your team, this gives them a sane starting point. If you don't, it gives you a clear picture of what you're hiring for.

The Mental Model Shift

Scripts and Functions solve the same problem in very different ways. The biggest mistake we see is people trying to port Scripts line-by-line. That doesn't work, because the underlying contract is different.

Scripts: Ruby code that runs inside Shopify's checkout, mutates a Cart object directly, and returns the mutated cart. You read properties, you write properties, you're done.

Functions: A WebAssembly module that receives a GraphQL input, returns a list of operations (FunctionRunResult), and lets Shopify apply those operations. You don't mutate state. You declare what should change.

If you internalize that one shift, the rest of the migration is mechanical.

The Migration Order We Run

We don't write a single line of Function code until steps 1 through 3 are done. Skipping ahead is how migrations slip three weeks past the deadline.

  1. Audit the Scripts. Read every active Script in Script Editor. Write down what each one does in plain English, including edge cases. Half the time, a Script does something the merchant forgot was even live.
  2. Map to native features. Shopify's native discount and checkout customization features have grown a lot since 2016. Several Scripts we audit each year don't need to become Functions. They can become native Automatic Discounts or Discount Combinations.
  3. Group what's left. The leftover Scripts get grouped by extension point. Discount logic goes to a Discount Function. Shipping logic goes to a Delivery Customization Function. Payment logic goes to a Payment Customization Function.
  4. Pick the toolchain. We build Functions on Gadget.dev because it cuts the boilerplate dramatically, but vanilla Shopify CLI plus a Rust or JS template works fine for a one-off.
  5. Translate, deploy, test in a development store, then promote. Never test Function changes against the live checkout. Use a dev store with the same product catalog shape.

A Real Translation: Tiered Discount

Here's the canonical "buy more, save more" Script that almost every Plus merchant has some version of.

Before (Ruby Script):

class TieredDiscount
  def run(cart)
    quantity = cart.line_items.reduce(0) { |sum, item| sum + item.quantity }

    discount_percent = case quantity
      when 0..2 then 0
      when 3..5 then 10
      when 6..9 then 15
      else 20
    end

    return if discount_percent == 0

    cart.line_items.each do |line_item|
      line_item.change_line_price(
        line_item.line_price * (Decimal.new(100 - discount_percent) / 100),
        message: "Tier discount (#{discount_percent}% off)"
      )
    end
  end
end

TieredDiscount.new.run(Input.cart)
Output.cart = Input.cart

Enter fullscreen mode Exit fullscreen mode

After (Shopify Function in JavaScript):

// src/run.js
export function run(input) {
  const totalQuantity = input.cart.lines.reduce(
    (sum, line) => sum + line.quantity,
    0
  );

  const discountPercent =
    totalQuantity >= 10 ? 20 :
    totalQuantity >= 6  ? 15 :
    totalQuantity >= 3  ? 10 : 0;

  if (discountPercent === 0) {
    return { discounts: [], discountApplicationStrategy: "FIRST" };
  }

  return {
    discounts: [
      {
        message: `Tier discount (${discountPercent}% off)`,
        targets: input.cart.lines.map((line) => ({
          productVariant: { id: line.merchandise.id, quantity: line.quantity }
        })),
        value: { percentage: { value: discountPercent.toString() } }
      }
    ],
    discountApplicationStrategy: "FIRST"
  };
}

Enter fullscreen mode Exit fullscreen mode

A few things to notice in the diff:

  • No mutation. We return a discounts array, we don't reach into the cart and rewrite line prices.
  • Targets are explicit. Scripts let you call change_line_price on each line. Functions ask you to declare which variants the discount applies to and how it stacks via discountApplicationStrategy.
  • The data shape is GraphQL. cart.line_items is now cart.lines, line_item.quantity is now line.quantity, and you'll spend the first hour of every migration relearning these names.

The GraphQL Input File Is Where People Get Stuck

Functions don't receive the entire cart. They receive whatever you ask for in an input.graphql query. This is the file that surprises every developer the first time.

# src/input.graphql
query Input {
  cart {
    lines {
      quantity
      merchandise {
        ... on ProductVariant {
          id
          product {
            id
            tags
          }
        }
      }
    }
  }
}

Enter fullscreen mode Exit fullscreen mode

If you forget to query tags here, you cannot read tags inside run.js, no matter how many console.log calls you add. The first hour of debugging a misbehaving Function is almost always "the input query is missing a field."

Shipping and Payment Customization

Scripts had a single execution point: checkout. Functions split that into separate APIs:

  • Delivery Customization Function for shipping. Hide options, rename them, reorder them.
  • Payment Customization Function for payment methods. Same operations.
  • Cart Transform Function if you need to expand a single line into multiple lines (bundles, components).

A Script that hid Express Shipping for heavy carts becomes a Delivery Customization Function that returns a hide operation:

export function run(input) {
  const totalGrams = input.cart.lines.reduce(
    (sum, line) => sum + (line.merchandise.weight ?? 0) * line.quantity,
    0
  );

  if (totalGrams < 20000) {
    return { operations: [] };
  }

  const expressOption = input.cart.deliveryGroups
    .flatMap((group) => group.deliveryOptions)
    .find((option) => option.title === "Express");

  if (!expressOption) {
    return { operations: [] };
  }

  return {
    operations: [
      { hide: { deliveryOptionHandle: expressOption.handle } }
    ]
  };
}

Enter fullscreen mode Exit fullscreen mode

The pattern is consistent across all three customization APIs: query what you need, decide what should change, return operations.

Gotchas We Hit Often

These are the ones that have actually cost us hours, not the ones we read about.

The instruction-count limit is real. Functions enforce a strict execution budget measured in instructions (around 11 million), not wall-clock time, along with a 125KB input size cap. Loops over the entire catalog, regex on every line item description, and deeply nested .find() chains will blow past it on a busy cart. Profile early.

undefined vs missing fields. GraphQL only returns what you queried. If a field isn't in input.graphql, it's not null in your input object, it's not present at all. Defensive code matters.

No external HTTP calls. Scripts didn't allow them either, but people sometimes assume Functions do because Functions are deployed as part of an app. They don't. If you need data from outside Shopify, fetch it ahead of time and pass it through metafields.

Discount stacking. Scripts let you stack discounts implicitly. Functions force you to declare a discountApplicationStrategy of FIRST or MAXIMUM. Pick the wrong one and your customers see different totals than they did under Scripts.

Localization and currency. Scripts gave you the cart's currency on the cart object. In Functions, you query it via cart.cost.totalAmount.currencyCode (or similar paths depending on the API). Hardcoding CAD because the dev store is in CAD is the kind of bug that ships to a US store and breaks Black Friday.

Testing tools are different. Scripts had a console in the admin. Functions are tested with shopify app function run against fixture inputs. Build out a small set of fixture carts that represent your real edge cases, and run them on every change.

How Long Does a Migration Take?

For a single straightforward Script (one rule, one extension point), expect a day of work end to end. Audit, translate, test, deploy.

For a Plus merchant with eight to twelve active Scripts spread across discounts, shipping, and payment, expect two to three weeks. Most of that time is in steps 1, 2, and 5. The actual coding is the smallest part.

If your store has Scripts you've forgotten about, has Scripts written by someone who left the company, or has Scripts that interact with each other in ways nobody documented, double the estimate. We've seen migrations that took six weeks because the audit kept turning up new edge cases.

How We Run Scripts to Functions Migrations

When clients bring us this work, our process is:

  1. Read-only audit week. We get Script Editor access, document everything, and produce a migration plan with native-feature swaps called out.
  2. Build week(s). Functions written, deployed to a dev store, tested against fixture carts that match the merchant's real traffic.
  3. Cutover. Functions enabled in production, Scripts disabled the same day. We watch checkout closely for 48 hours.
  4. Post-cutover review. We document what changed and hand the codebase off, since Functions live in a real Git repo, not in an admin panel.

If you're sitting on Scripts and the June 30 deadline is starting to feel close, get in touch. We can run the audit week and tell you exactly how big the project is before you commit to a build. For more on how we build Functions and apps quickly, see why we build Shopify apps on Gadget.dev and our Shopify app development service.

The Bottom Line

The migration isn't conceptually hard. It's a translation job between two systems that solve the same problem. The discipline is in the audit and the testing, not the coding. Start with what you have, map what's native, and write Functions only for what's actually left.

The merchants who started this work in 2025 are done. The ones who started in early 2026 are mid-project. The ones who haven't started yet still have time, but the runway is roughly eight weeks and shrinking.