Development
9/11/2025
8 min read

Building a Custom Shipping Module in Shopify Using CarrierService (2025-Version)

Shipping can make or break the checkout experience. Here’s how to build a custom Shopify shipping module with the CarrierService API for accurate, real-time rates.

S
SBO Tech Team
Lead Developer
Building a Custom Shipping Module in Shopify Using CarrierService (2025-Version)

Build a Custom Shopify CarrierService (Carrier-Calculated Shipping) — 2025 Guide

Shipping is a critical part of e-commerce. A custom Shopify CarrierService (also called carrier-calculated shipping or delivery carrier service) lets you return real-time shipping rates in checkout — ideal when you need carrier quotes, advanced rate logic, or region-specific pricing. For reference, Shopify documents CarrierService as the API that provides real-time rates to checkout. :contentReference[oaicite:0]{index=0}

Why build a custom shipping module (CarrierService)?

  • Fetch real-time shipping quotes from your regional couriers or your own rate tables.
  • Implement advanced rate rules — combinations of cart weight, order value, shipping zones, or surcharges for oversized items.
  • Offer tiered shipping: free shipping above thresholds, express vs standard, pickup options, etc.

Key concepts: what CarrierService (Delivery Carrier Service) returns and expects

When Shopify needs rates it POSTs a rate request (origin, destination, line items with grams/quantity/price, currency, locale) to your callbackUrl. Your app responds with one or more rate objects containing service_name, service_code, and total_price (in smallest currency unit). See Shopify docs for the exact fields required. :contentReference[oaicite:1]{index=1}

Important compatibility & API note (2025)

As of Shopify’s 2024–2025 developer updates, new public apps submitted after April 1, 2025, must use the GraphQL Admin API — plan your app architecture accordingly (GraphQL is the recommended path for new apps). :contentReference[oaicite:2]{index=2}

Requirements & prerequisites

  1. Shopify plan / feature access — the store must be eligible for carrier-calculated/shipping apps (Advanced/Plus or carrier-calculated feature enabled for the store or development store).
  2. API scopes — your app needs the shipping scope (e.g., write_shipping) to register or manage carrier services.
  3. Public HTTPS endpoint — callback URL must be reliable, HTTPS, and fast (see timeouts below).
  4. Use GraphQL — build new public apps on GraphQL Admin API when possible. :contentReference[oaicite:3]{index=3}

Step-by-step: build & register a custom CarrierService

Step 1 — create your app & request shipping scopes

Create a custom app (or public app via OAuth) and request the appropriate shipping scopes (write_shipping). Avoid private apps for public distribution.

Step 2 — register the carrier service (GraphQL recommended)

Use the GraphQL Admin API to create a DeliveryCarrierService; REST endpoints still exist for legacy use, but GraphQL is the recommended API for new apps. Example GraphQL mutation:


mutation CarrierServiceCreate($input: DeliveryCarrierServiceCreateInput!) {
  carrierServiceCreate(input: $input) {
    carrierService {
      id
      name
      callbackUrl
      active
      supportsServiceDiscovery
    }
    userErrors {
      field
      message
    }
  }
}
  

Variables example:

{
  "input": {
    "name": "My Custom Carrier Service",
    "callbackUrl": "https://your-callback.example.com/rates",
    "supportsServiceDiscovery": true,
    "active": true
  }
}

REST example (legacy)

If you must support REST for older integrations, you can POST to /admin/api/{version}/carrier_services.json with equivalent fields (service_discovery / callback_url), but prefer GraphQL for new apps. :contentReference[oaicite:4]{index=4}

Step 3 — handle Shopify rate callbacks (Node.js example)

Shopify will POST a rate object to your callback URL. Below is a minimal Node.js/Express example showing how to calculate rates based on total weight:


// server.js (minimal example)
const express = require('express');
const bodyParser = require('body-parser');
const app = express();
app.use(bodyParser.json());

app.post('/calculate_shipping', (req, res) => {
  try {
    const rateRequest = req.body.rate || {};
    const items = rateRequest.items || [];
    let totalWeight = 0;
    for (const item of items) {
      if (item.requires_shipping) totalWeight += (item.grams || 0) * (item.quantity || 1);
    }

    function calculateYourRate(totalWeight) {
      const base = 500; // cents
      const perGram = 0.2; // cents per gram
      return Math.round(base + totalWeight * perGram);
    }

    const cost = calculateYourRate(totalWeight);
    const currency = rateRequest.currency || 'USD';

    const rates = [
      {
        service_name: "Standard Shipping",
        service_code: "standard",
        total_price: cost.toString(),
        description: "Delivery in 5-7 business days",
        currency: currency
      },
      {
        service_name: "Express Shipping",
        service_code: "express",
        total_price: (cost * 2).toString(),
        description: "Delivery in 2-3 business days",
        currency: currency
      }
    ];

    res.json({ rates: rates });
  } catch (err) {
    console.error(err);
    res.json({ rates: [] });
  }
});

app.listen(3000, () => console.log('Listening on 3000'));
  

Step 4 — configure the service in Shopify Admin

After registration, enable and add your carrier/app rate under Shopify Admin → Settings → Shipping and Delivery → Shipping profiles (add the app rates to the shipping profile and confirm eligible zones). :contentReference[oaicite:5]{index=5}

Step 5 — test extensively

  • Test multiple origins/destinations (domestic & international), cart weights, and oversize items.
  • Verify free-shipping thresholds and tiered rates.
  • Test fallback behaviour: what happens when your endpoint is down or returns invalid JSON.

Performance, timeouts & best practices

Shopify applies dynamic read timeouts to CarrierService rate requests based on requests per minute (RPM). Timeout tiers have historically been documented (e.g., under 1500 RPM → ~10s, 1500–3000 → ~5s, >3000 → ~3s). To avoid timeouts and blocked checkouts, keep responses fast, cache identical requests, and parallelize external carrier calls. :contentReference[oaicite:6]{index=6}

Best practice checklist

  • Cache/memoize identical requests (same origin/destination + items) to serve fast cached rates.
  • Parallelize external carrier API calls and set conservative internal timeouts (return partial rates if needed).
  • Return prices in subunits (cents) and match the store currency exactly.
  • Use supportsServiceDiscovery to enable dummy/test requests from Shopify admin for easier debugging.
  • Instrument logging and expose anonymized logs to merchants for debugging test requests.

Common pitfalls & troubleshooting

Timeouts: slow 3rd-party carrier APIs are the most common cause of missing rates — use caching and timeouts.

Wrong currency or units: send total_price in the store's smallest currency unit (e.g., cents), or Shopify may reject the rate.

Plan restrictions: carrier calculations depend on the merchant’s plan/feature flag — ensure store eligibility before expecting rates to show.

SEO & developer tips (to make this page convert)

  • Add a downloadable code sample (zip) with a Node.js + GraphQL example — users will link to it.
  • Add in-page schema (FAQ schema) for the Q/A below — increases SERP real estate.
  • Internal links: link to other developer guides — e.g., "Shopify App auth", "Admin GraphQL guide", "shipping profiles" with anchor text using secondary keywords.

FAQ

What is the difference between CarrierService and carrier-calculated shipping?

CarrierService is Shopify’s API resource (DeliveryCarrierService) used to provide carrier-calculated shipping rates at checkout. “Carrier-calculated shipping” is the general feature of showing real-time carrier rates in checkout; CarrierService is the programmatic way to provide those rates. :contentReference[oaicite:7]{index=7}

Should I use GraphQL or REST to create a carrier service in 2025?

For new public apps, Shopify requires GraphQL (post-April 1, 2025). Use GraphQL Admin API for new apps and features; REST is legacy for new public apps. :contentReference[oaicite:8]{index=8}

How fast must my callback respond?

Shopify applies dynamic read timeouts depending on RPM (example tiers: ~10s/5s/3s). Design your service to respond quickly and cache responses for identical requests to avoid timeouts. :contentReference[oaicite:9]{index=9}

Need a code review or help shipping-proofing your CarrierService? If you want, I can: (A) produce a deployable Node.js + Express + GraphQL example that registers a DeliveryCarrierService and handles caching, or (B) suggest a testing checklist and Postman/insomnia collection you can import.

4) Quick on-page / technical checklist to implement right away Add the meta title/description and canonical (see above). Add JSON-LD FAQ (the FAQ in the HTML is already schema-ready). Use the slug /blog/shopify-carrierservice-custom-shipping-module. Add a featured image (no text on image), alt: Shopify CarrierService custom shipping module. Add internal links to: developer > GraphQL Admin API, shipping profiles, and any existing shipping app posts. Use anchor text like “Shopify CarrierService” and “register a carrier service”. Submit the new URL to Google Search Console and monitor for index/coverage. Add structured headers (H1 / H2 / H3) exactly as in the HTML to maximize relevance. 5) Next steps I can do for you (pick any) Generate the deployable Node.js + GraphQL sample repo (ready to run) — includes caching + timeout handling. Produce 5 social snippets (LinkedIn/Twitter) and a lightweight promo meta image (title on image) to boost initial traction. Export a short checklist + Postman collection for testing the app. Sources / references (most important citations) Shopify CarrierService / DeliveryCarrierService docs. Shopify Shopify developer announcement — new public apps must use GraphQL starting April 1, 2025. Shopify CarrierService response timeouts & caching recommendations. Shopify +1 Shopify admin shipping profiles (where to enable carrier/app rates). Shopify Help Center If you want, I can now: produce the downloadable Node.js + GraphQL example (deployable), or deliver a plain-text / markdown version of the optimized article for your CMS, or run a quick competitor keyword check (SERP titles for top 10 results) and suggest 1–2 title tweaks to outrank them. Which of those would you like me to do next?
S

About SBO Tech Team

Expert in Shopify app development.

Want to Read More?

Explore more insights and tutorials on Shopify development and e-commerce optimization.

Browse All Posts