> ## Documentation Index
> Fetch the complete documentation index at: https://docs.devin.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Migrate 50 Files from REST to GraphQL

export const UseCaseHero = ({title, description, prompt, category, features, devinUrl, agent, intent, playbookId, type}) => {
  const encodedPrompt = encodeURIComponent(prompt || '');
  const tag = 'docs-use-case-gallery';
  const utm = 'utm_source=docs&utm_medium=use-case-gallery&utm_campaign=hero-cta';
  const agentParams = (agent ? '&agent=' + agent : '') + (intent ? '&intent=' + intent : '') + (playbookId ? '&playbookId=' + playbookId : '');
  const devinHref = type === 'schedule' ? 'https://app.devin.ai/settings/schedules/create?' + utm + agentParams + (prompt ? '&prompt=' + encodedPrompt : '') : type === 'review' ? 'https://app.devin.ai/review?' + utm : agent === 'ada' ? 'https://app.devin.ai/search?' + utm + '&noSubmit=true' + (prompt ? '&prompt=' + encodedPrompt : '') : devinUrl ? devinUrl.includes('?') ? devinUrl + '&' + utm + agentParams : devinUrl + '?' + utm + agentParams : prompt ? 'https://app.devin.ai/?tags=' + tag + '&' + utm + agentParams + '&prompt=' + encodedPrompt : 'https://app.devin.ai/?' + utm + agentParams;
  const buttonLabel = type === 'schedule' ? 'Schedule in Devin ↗' : type === 'review' ? 'Set Up Devin Review ↗' : agent === 'advanced' ? 'Try in Devin ↗' : agent === 'dana' ? 'Try in Dana ↗' : agent === 'ada' ? 'Try in Ask Devin ↗' : 'Try in Devin ↗';
  const featureList = features ? features.split(',').map(f => f.trim()) : [];
  return <div className="uc-hero">
      <div className="uc-hero-inner">
        <div className="uc-hero-left">
          <h1 className="uc-hero-title">{title}</h1>
          <p className="uc-hero-desc">{description}</p>
          <div>
            <a href={devinHref} target="_blank" rel="noopener noreferrer" className="try-in-devin-btn">
              {buttonLabel}
            </a>
          </div>
        </div>
        <div className="uc-hero-meta">
          <div className="uc-meta-item">
            <span className="uc-meta-label">Author</span>
            <span className="uc-meta-value">Cognition</span>
          </div>
          <div className="uc-meta-item">
            <span className="uc-meta-label">Category</span>
            <span className="uc-meta-value">{category}</span>
          </div>
          {featureList.length > 0 && <div className="uc-meta-item">
              <span className="uc-meta-label">Features</span>
              <span className="uc-meta-value">{featureList.join(', ')}</span>
            </div>}
        </div>
      </div>
    </div>;
};

export const PromptBlock = ({children, type, agent, intent, playbookId}) => {
  var utm = 'utm_source=docs&utm_medium=use-case-gallery&utm_campaign=prompt-block';
  var tag = 'docs-use-case-gallery';
  var agentParams = (agent ? '&agent=' + agent : '') + (intent ? '&intent=' + intent : '') + (playbookId ? '&playbookId=' + playbookId : '');
  var label = type === 'schedule' ? 'Schedule in Devin' : type === 'playbook' ? 'Create Playbook' : type === 'knowledge' ? 'Add to Knowledge' : agent === 'advanced' ? 'Try in Devin' : agent === 'dana' ? 'Try in Dana' : agent === 'ada' ? 'Try in Ask Devin' : 'Try in Devin';
  var buildUrl = function (text) {
    var encoded = encodeURIComponent(text);
    if (type === 'schedule') return 'https://app.devin.ai/settings/schedules/create?' + utm + agentParams + '&prompt=' + encoded;
    if (type === 'playbook') return 'https://app.devin.ai/settings/playbooks/create?' + utm + '&body=' + encoded;
    if (type === 'knowledge') return 'https://app.devin.ai/knowledge?' + utm + '&body=' + encoded;
    if (agent === 'ada') return 'https://app.devin.ai/search?' + utm + '&noSubmit=true&prompt=' + encoded;
    return 'https://app.devin.ai/?tags=' + tag + '&' + utm + agentParams + '&prompt=' + encoded;
  };
  const ref = React.useRef(null);
  const [href, setHref] = React.useState('#');
  React.useEffect(() => {
    if (!ref.current) return;
    var codeEl = ref.current.querySelector('pre code');
    if (codeEl) {
      var text = codeEl.textContent.trim();
      if (text) setHref(buildUrl(text));
    }
    var header = ref.current.querySelector('[data-component-part="code-block-header"]');
    if (header && !header.querySelector('.prompt-block-devin-link')) {
      var link = document.createElement('a');
      link.href = href;
      link.target = '_blank';
      link.rel = 'noopener noreferrer';
      link.className = 'prompt-block-devin-link';
      link.style.cssText = 'display:inline-flex;align-items:center;gap:6px;text-decoration:none;color:#fff;font-size:11px;font-weight:500;padding:4px 10px;border-radius:6px;white-space:nowrap;background:#317CFF;transition:background 0.2s;margin-left:8px;';
      link.innerHTML = '<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"/><polyline points="15 3 21 3 21 9"/><line x1="10" y1="14" x2="21" y2="3"/></svg> ' + label;
      link.onmouseenter = function () {
        link.style.background = '#2968D9';
      };
      link.onmouseleave = function () {
        link.style.background = '#317CFF';
      };
      header.appendChild(link);
    }
    var existingLink = ref.current.querySelector('.prompt-block-devin-link');
    if (existingLink && href !== '#') existingLink.href = href;
  });
  return <div className="prompt-block" ref={ref}>{children}</div>;
};

<UseCaseHero title="Migrate 50 Files from REST to GraphQL" description="Scope a 50-file REST-to-GraphQL migration, split it into conflict-free work packages, and run them all at once with managed Devins." prompt="Analyze our codebase for all files using the legacy REST client. Group them into independent work packages that won't conflict, then start a parallel Devin session for each package to migrate to the new GraphQL client." category="Migrations" features="Advanced, Playbooks" agent="advanced" intent="batch" />

<div className="uc-detail-wrapper">
  <Tip>Don't want to set this up manually? Paste a link to this page into a Devin session and ask it to set everything up for you.</Tip>

  <Steps>
    <Step title="Scope the migration with Ask Devin">
      You have 50 files that import from `src/lib/restClient.ts` and need to move to the new `graphqlClient`. Before splitting anything into parallel work, you need to know how those files are connected. Use [Ask Devin](/work-with-devin/ask-devin) to map the migration surface area — which files import the legacy client, how they cluster by domain, and where the risky coupling lives. Devin uses [DeepWiki](/work-with-devin/deepwiki) and semantic search under the hood, so it can answer these questions grounded in your actual code.

      <Tip>Ask Devin requires your repository to be [indexed](/onboard-devin/index-repo). Go to [**Settings > Repositories**](https://app.devin.ai/settings/repositories?utm_source=docs\&utm_medium=use-case-gallery) to check indexing status or index a new repo.</Tip>

      Open [Ask Devin](https://app.devin.ai/search?utm_source=docs\&utm_medium=use-case-gallery) and ask:

      <PromptBlock agent="ada">
        ```txt Scope the REST-to-GraphQL migration theme={null}
        How many files import from src/lib/restClient.ts? Group them by
        domain (user management, billing, analytics, notifications, auth,
        admin, search, onboarding, etc.) and flag any files that share
        state or have tight coupling across domains.
        Note which files have existing test coverage.
        ```
      </PromptBlock>

      Ask Devin returns a breakdown like this:

      ```
      50 files import restClient across 8 domains:

        User Management  (7 files) — isolated, full test coverage
        Billing          (9 files) — isolated, 6/9 tested
        Analytics        (5 files) — isolated, 3/5 tested
        Auth             (6 files) — shared middleware, full test coverage
        Notifications    (8 files) — isolated, 5/8 tested
        Admin            (5 files) — depends on Auth middleware
        Search           (4 files) — isolated, 2/4 tested
        Onboarding       (6 files) — isolated, 4/6 tested

      Coupling note: Admin imports requireAuth from Auth. Migrate
      Auth first, then Admin. All other domains are independent.
      ```

      This tells you whether parallelization makes sense. If most files are tightly coupled across domains, a sequential migration is safer. Here, 6 of 8 domains are fully independent — you can run them in parallel.
    </Step>

    <Step title="Create a migration playbook">
      Every parallel session should follow the same migration pattern so the resulting PRs are consistent and easy to review. Create a [playbook](/product-guides/creating-playbooks) that defines exactly how each file should be migrated.

      Go to [**Settings > Playbooks > Create Playbook**](https://app.devin.ai/settings/playbooks/create?utm_source=docs\&utm_medium=use-case-gallery) and define the steps:

      <PromptBlock type="playbook">
        ```txt REST to GraphQL Migration theme={null}
        For each file assigned to you:

        1. Replace `import { restClient } from 'src/lib/restClient'`
           with `import { graphqlClient } from 'src/lib/graphqlClient'`
        2. Rewrite each API call to use the corresponding GraphQL
           query or mutation defined in src/graphql/operations/
        3. Update error handling from HTTP status codes to GraphQL
           error types (see src/lib/graphqlClient.ts for the error map)
        4. Update the corresponding test file:
           - Replace REST endpoint mocks with GraphQL mocks using msw
           - Assert on the GraphQL operation name, not the URL
        5. Run `npm run typecheck && npm test -- --related` to verify
        6. Open a PR titled: "migrate: [domain] REST → GraphQL"
        ```
      </PromptBlock>

      Or ask Devin to generate the playbook for you — describe your migration pattern and it will produce a complete playbook:

      <PromptBlock agent="advanced">
        ```txt Generate a REST-to-GraphQL migration playbook theme={null}
        Create a playbook for migrating files from our REST client
        (src/lib/restClient.ts) to our new GraphQL client
        (src/lib/graphqlClient.ts). Look at src/graphql/operations/ for
        the available queries and mutations. Include steps for updating
        imports, rewriting API calls, converting error handling from HTTP
        status codes to GraphQL error types, updating tests to use msw
        GraphQL mocks, and running typecheck + tests.
        ```
      </PromptBlock>

      Referencing this playbook in your orchestration prompt ensures all parallel sessions produce PRs that look like they came from the same developer.
    </Step>

    <Step title="Launch parallel sessions with Devin">
      Open a new Devin session from the [Devin home page](https://app.devin.ai/?utm_source=docs\&utm_medium=use-case-gallery) and give it the orchestration prompt. Devin analyzes your codebase's dependency graph, creates independent work packages, and launches one session per package — all running simultaneously.

      <PromptBlock agent="advanced" intent="batch">
        ```txt Parallelize REST-to-GraphQL migration across 50 files theme={null}
        Analyze our codebase and find every file that imports from
        src/lib/restClient.ts. Map the dependency graph between these
        files to identify groups that can be migrated independently —
        no two groups should modify the same file or share mutable state.

        For each independent group, start a parallel Devin session using
        the "REST to GraphQL Migration" playbook. Each session should:
        - Migrate only its assigned files
        - Run typecheck and tests for its scope
        - Open a separate PR

        Before starting sessions, show me the proposed grouping so I can
        approve it. Include file counts and estimated complexity per group.
        ```
      </PromptBlock>

      Devin presents a grouping for your approval before launching anything:

      ```
      Proposed work packages (8 groups, 50 files total):

      Group 1 — User Management (7 files, complexity: M)
        src/services/UserService.ts, src/pages/Profile.tsx,
        src/pages/Settings.tsx, src/hooks/useCurrentUser.ts,
        src/pages/UserDirectory.tsx, src/services/AvatarService.ts,
        src/components/UserCard.tsx

      Group 2 — Billing (9 files, complexity: L)
        src/services/BillingService.ts, src/services/InvoiceService.ts,
        src/services/SubscriptionService.ts, src/pages/Checkout.tsx,
        src/pages/PlanSelector.tsx, src/pages/InvoiceHistory.tsx,
        src/components/PaymentForm.tsx, src/hooks/useSubscription.ts,
        src/components/PricingTable.tsx

      Group 3 — Analytics (5 files, complexity: S)
        src/services/AnalyticsService.ts, src/pages/Dashboard.tsx,
        src/components/MetricsCard.tsx, src/hooks/useMetrics.ts,
        src/components/ChartPanel.tsx

      Group 4 — Auth (6 files, complexity: L) ⚠ migrate first
        src/services/AuthService.ts, src/middleware/requireAuth.ts,
        src/middleware/refreshToken.ts, src/pages/Login.tsx,
        src/pages/Signup.tsx, src/services/SessionService.ts

      Group 5 — Notifications (8 files, complexity: M)
        src/services/NotificationService.ts, src/services/EmailService.ts,
        src/services/PushService.ts, src/pages/NotificationPreferences.tsx,
        src/components/NotificationBell.tsx, src/hooks/useNotifications.ts,
        src/components/NotificationToast.tsx, src/services/WebhookService.ts

      Group 6 — Admin (5 files, complexity: M) ⚠ depends on Auth
        src/pages/AdminDashboard.tsx, src/pages/AdminUsers.tsx,
        src/services/AdminService.ts, src/components/AdminSidebar.tsx,
        src/middleware/requireAdmin.ts

      Group 7 — Search (4 files, complexity: S)
        src/services/SearchService.ts, src/pages/SearchResults.tsx,
        src/components/SearchBar.tsx, src/hooks/useSearch.ts

      Group 8 — Onboarding (6 files, complexity: M)
        src/services/OnboardingService.ts, src/pages/Welcome.tsx,
        src/pages/SetupWizard.tsx, src/components/ProgressTracker.tsx,
        src/hooks/useOnboardingState.ts, src/services/ChecklistService.ts

      Dependency note: Group 6 (Admin) imports middleware from Group 4
      (Auth). Will launch Auth first, then Admin after Auth's PR merges.
      Launch remaining 6 groups in parallel immediately.

      Start 6 parallel sessions now + 2 sequential? (y/n)
      ```

      Approve the grouping and six sessions launch at once. Auth runs first, then Admin follows once Auth merges.
    </Step>

    <Step title="Review and merge the results">
      Each session opens its own PR. Since the packages are independent, you can review and merge them in any order — but merge Auth first since Admin depends on it, and run full CI after each merge to catch any unexpected interactions.

      Once all 8 migration PRs are merged, use a follow-up session to clean up dead code:

      <PromptBlock>
        ```txt Post-migration cleanup theme={null}
        All REST-to-GraphQL migration PRs are merged. Scan the codebase for:
        1. Any remaining imports of src/lib/restClient.ts
        2. Dead code in shared utilities that only the REST client used
        3. REST-specific types or interfaces that can be removed

        Clean them up and delete src/lib/restClient.ts entirely if nothing
        imports it anymore.
        ```
      </PromptBlock>
    </Step>
  </Steps>
</div>
