Всего за год нагрузка на Cursor выросла в 100 раз: более 1 млн запросов в секунду и миллиарды автодополнений кода каждый день. Подробный разбор архитектуры — вместе с сооснователем Суалехом Асифом.

Cursor — это IDE с кодогенерацией на AI-агентах, которая сейчас пользуется наибольшей популярностью среди разработчиков. В прошлогоднем опросе, Cursor был самым частым ответом на вопрос «Назовите вашу любимую IDE с генерацивными функциями, помогающими в работе».

Стартап, стоящий за Cursor — Anysphere, был основан в 2022 году, а в марте 2023 года запустил Cursor. Недавно Anysphere сообщила, что привлекла $900 млн, при оценке компании в $9.9B. Годовой доход уже превысил $500M. Ни одна другая компания в сфере инструментов для разработчиков, которую я знаю, не достигала этого рубежа в течение первых 2 лет после запуска первого продукта. Поспособствовало этому и то, что Cursor используется более чем половиной из 500 крупнейших технологических компаний из списка Fortune 500.

Я встретился с сооснователем Cursor, Суалехом Асифом, чтобы узнать, как работает Cursor и как команда этот инструмент создает. Обсудили следующие темы:

  1. Технологический стек. TypeScript, Rust и куча облачных провайдеров — Turbopuffer, Datadog, PagerDuty и другие.

  2. Как работает автодополнение. Устройство движка, который передает зашифрованный контекст на сервер для инференса с минимальными задержками.

  3. Как работает чат по коду, если код на сервере не хранится. Использование хеш-деревьев, код ищем по эмбеддингам. (Из интересного тут, как шатать огромную кодовую базу. Прим пер.)

  4. Anyrun: Сервис-оркестратор на Rust, который занимается запуском агентов в облаке, используя Amazon EC2 и AWS Firecracker.

  5. Инженерные вызовы. Ограничения на выбор технологий, проблемы масштабирования, проблема «холодного старта», сложности с шардированием и труднообнаруживаемые сбои.

  6. Миграция баз данных. Как и почему Cursor перешёл с Yugabyte (БД, которая должна была масштабироваться бесконечно) на PostgreSQL. А также про эпическую историю по переходу на Turbopuffer за пару часов во время критического сбоя.

  7. Культура кода и процессы. Релизы каждые 2-4 недели, выделенная команда инфраструктуры, культура экспериментов и другие интересные задачи, с которыми они сталкиваются.

Cursor в цифрах

Прежде чем мы перейдем к тех. стеку, давайте посмотрим на небольшую статистику:

  • 50: количество инженеров, работающих над Cursor

  • 1M: транзакций в секунду (и выше при пиковой нагрузке)

  • 100x: рост пользователей и нагрузки за 12 месяцев, временами удваиваясь каждый месяц

  • 100M+: строк кода, написанного в день с помощью Cursor корпоративными клиентами, такими как NVIDIA, Uber, Stripe, Instacart, Shopify, Ramp, Datadog и другими. Cursor утверждает, что более 50% из 1000 крупнейших американских компаний используют его продукты.

  • $500M+: годовой доход. В в начале мая эта цифра составляла $300M, а в январе — $100M, по сравнению с нулем год назад.

  • 1 000 000 000: чуть меньше этого количества строк кода пишется с помощью Cursor ежедневно корпоративными и некорпоративными пользователями

  • Сотни терабайт: объем индексов, хранящихся в базах данных Cursor. Это может показаться менее впечатляющим, чем другие цифры, но сам код довольно мал по объему хранения по сравнению с изображениями и видео. Кроме того, это не сам код, а эмбеддинги, поскольку Cursor не хранит код в своих базах данных.

Cursor может догнать GitHub Copilot по объему выручки: Reuters сообщает, что GitHub Copilot, вероятно, сделал $500M выручки в 2024 году. В настоящее время Cursor находится на пути к тому, чтобы получить столько же в 2025 году, или даже больше, если рост продолжится текущими темпами.

1. Технологический стек

Еще немного чисел по кодовой базе Cursor, которой едва исполнилось 3 года:

  • 25 000 файлов

  • 7 миллионов строк кода

Сам редактор — это форк Visual Studio Code и у него тот же технологический стек, что и у VS Code:

  • TypeScript: большая часть бизнес-логики написана на нем

  • Electron: фреймворк, используемый Cursor

При создании компании парням нужно было решить, создавать редактор с нуля, как это сделали в Zed, или начать с форка. Суалех объясняет это решение так:

«Нам нужно было иметь собственный редактор, а не быть просто расширением, потому что мы хотели изменить сам способ программирования. Это означало, что нам нужно было либо создать совершенно новую IDE, либо форкнуть уже существующий редактор.

Мы решили форкнуть, потому что работа с нуля потребовала бы огромных усилий только для того, чтобы просто написать стабильный редактор. Наше ценностное предложение заключалось не в создании стабильного редактора, а в изменении того, как разработчики программируют, делая это постепенно. Например, создание новой «модели вкладок» было бы очень сложным без форка, а с форком это было тривиально. Форк позволил нам сосредоточиться на UX, а не на редакторе».

Бэкенд

  • TypeScript: большая часть бизнес-логики.

  • Rust: все критически важные для производительности компоненты. Оркестратор, о котором пойдет речь ниже, тоже написан на Rust'е.

  • Node API для Rust: большая часть бизнес-логики находится в TypeScript, а части, требующие высокой производительности на Rust, поэтому существует интерфейс для вызова кода Rust из TypeScript через Node.js. Одним из примеров является вызов логики индексации (написанной на Rust), которая активно использует этот интерфейс.

  • Один основной сервис: по большей части бэкенд представляет собой здоровенный монолит и развертывается как единое целое. Это напоминание о том, что монолиты довольно хорошо работают для стартапов на ранней стадии и могут помочь командам двигаться быстро.

Базы данных

  • Turbopuffer: база данных, используемая для хранения зашифрованных файлов и хеш-деревьев рабочего пространства, о чем будет рассказано ниже. Команда выбрала эту БД за её масштабируемость и отсутствие необходимости иметь дело с шардированием, как раньше. Мы рассмотрим проблемы в разделе «Инженерные вызовы» ниже.

Turbopuffer

  • Pinecone: векторная БД c эмбеддингами для документации.

Стриминг

  • Warpstream: сервис потоковой передачи данных, совместимый с Apache Kafka.

Инструменты

  • Datadog: логирование и мониторинг. Суалех говорит, что команда считает этот сервис лучшим из альтернативных решений.

  • PagerDuty: управление дежурствами, интегрировано со Slack'ом.

  • Slack: внутренняя коммуникация и чат.

  • Sentry: мониторинг ошибок.

  • Amplitude: аналитика.

  • Stripe: биллинг и платежи.

  • WorkOS: аутентификация при входе в Cursor, например, вход через GitHub или Google Workspace.

  • Vercel: платформа, на которой размещен веб-сайт cusor.com.

  • Linear: менеджмент.

  • Cursor: Команда использует Cursor для создания Cursor! Каждый инженер несет ответственность за свой собственный добавленный код, независимо от того, написал ли он его вручную или сгенерировал с помощью Cursor.

Обучение моделей: Используем несколько провайдеров для обучения собственных моделей и дообучения существующих:

  • Voltage Park

  • Databricks MosaicML

  • Foundry

Физическая инфраструктура

Вся инфраструктура работает на облачных провайдерах. Суалех говорит:

«Можно сказать, что мы «облачная компания». В основном мы полагаемся на AWS, а затем на Azure для инференса. Также мы используем несколько других, менее известных облаков с GPU».

Большая часть CPU-инфраструктуры работает на AWS. Также AWS оперирует десятками тысяч GPU NVIDIA H100. Значительная часть GPU работает в Azure. (Тут и дальше по тексту не до конца понятно точное распределение GPU по провайдерам (прим пер.))

20 GPU NVIDIA H100 в дата-центре Microsoft Azure. Вычислительные потребности Cursor эквивалентны тысячам таких стоек. Источник: NVIDIA

Инференс — это, безусловно, самый большой сценарий использования GPU для Cursor, будь то автодополнение или кодогенерация. По факту, GPU в Azure используются исключительно для инференса, а не для другой работы типа обучения моделей.

Terraform — для управления инфраструктурой, такой как GPU и виртуалки, например, инстансы EC2.

2. Как работает автодополнение

Чтобы понять технические проблемы создания Cursor, давайте посмотрим, что происходит при первом запуске IDE.

Ваш проект

Low-latency синхронизация: автодополнение

При открытии проекта или папки вы, скорее всего, начнете редактировать файлы. Это означает, что Cursor должен генерировать варианты автодополнения, которые команда называет «tab-дополнениями».

Движок синхронизации с низкой задержкой лежит в основе «tab-модели». Он генерирует ваиранты, которые выделены серым и могут быть приняты нажатием клавиши «Tab». Предложения должны генерироваться быстро, в идеале менее чем за секунду. Вот что происходит за кулисами:

Как работают «предложения по tab'у» в Cursor

  1. Небольшая часть текущего контекстного окна с кодом собирается локальным клиентом

  2. Код шифруется

  3. Зашифрованный код отправляется на бэкенд

  4. Бэкенд расшифровывает код

  5. С использованием собственной LLM-модели Cursor генерируются варианты дополнений

  6. Все это отправляется обратно

  7. IDE отображает дополнение. Нажатие «Tab» принимает его

  8. …процесс повторяется

Эта «tab-модель» должна быть максимально быстрой, а задержка — минимальной. Всегда существует компромисс между тем, сколько контекста отправлять, и качеством дополнений: чем более полный и релевантный контекст может отправить Cursor, тем лучше будут дополнения. Однако отправка большого количества контекста замедляет работу.

3. Как работает чат по коду без хранения кода на сервере

Cursor поддерживает режим чата для запросов по кодовой базе, «общения» с ней и, главное, для запуска агентов для рефакторинга и добавления новой функциональности. Исходный код не хранится на бэкенде, но все операции с LLM выполняются там. Делается это при помощи индексов кодовой базы. Вот как это работает:

Чат с кодом: возьмем пример с вопросом о некотороом методе createTodo(), который определен в файле server.js. Чтобы усложнить задачу, я определил похожий метод addTodo() в index.html. Посмотрим, как Cursor справится с этим!

Запрос в Cursor, связанный с вашей кодовой базой

Запрос отправляется на сервер, где он интерпретируется и решается, что необходимо выполнить поиск по кодовой базе:

Начинается поиск:

Поиск выполняется с использованием индексов кодовой базы. Индексы тут — это предварительно созданные эмбеддинги. Он пытается найти эмбеддинги, которые наилучшим образом соответствуют контексту, с помощью векторного поиска. В данном случае векторный поиск вернул два очень близких результата: в server.js и index.html (просто RAG по коду, прим. пер.).

Запрос кода от клиента: сервер не хранит исходный код, но теперь запрашивает исходный код как из server.js, так и из index.html, чтобы он мог проанализировать оба и решить, какой из них релевантен:

Наконец, после векторного поиска и запроса релевантного кода от клиента, у сервера есть контекст, необходимый для ответа на вопрос:

Есть еще пара интересных вещей, происходящих за кулисами.

Семантическая индексация кусков вашего кода

Для адекватного векторного поиска по эмбеддингам код сначала разбивается на более мелкие фрагменты, по ним создаются эмбеддинги, которые хранятся на сервере:

  1. Бьем код на чанки. Каждая часть позже станет эмбеддингом.

  2. Создание эмбеддингов без хранения имен файлов или кода. Cursor не хранит даже имена файлов на сервере, потому что это может считаться конфиденциальной информацией. Вместо этого он передает на сервер обфусцированные имена файлов и зашифрованные фрагменты кода. Сервер расшифровывает код, создает эмбеддинг с использованием эмбеддингов от OpenAI или одной из своих собственных, и сохраняет их в своей векторной базе данных — Turbopuffer.

Создание эмбеддингов является вычислительно затратным и является одной из причин, почему это делается на бэкенде с использованием GPU в облаке. Индексация обычно занимает менее минуты для кодовых баз среднего размера. Вы можете просмотреть статус индексации меню Settings → Indexing:

Поддержание индекса в актуальном состоянии с помощью хеш-деревьев (деревья Меркла)

По мере того как вы редактируете код в Cursor или другой IDE, индекс на сервере устаревает. Наивным решением было бы запускать операцию переиндексации каждые несколько минут. Однако, поскольку индексация является дорогостоящей операцией и забивает канал передачи зашифрованными фрагментами кода, то это не идеально. Вместо этого Cursor хитроумно использует хеш-деревья и движок синхронизации с более высокой задержкой (синхронизация запускается каждые 3 минуты), чтобы поддерживать индексы на сервере в актуальном состоянии.

Хеш-дерево (дерево Меркла) — это дерево, каждый лист которого является хэшем базового файла (например, хэш для файла main.js). И каждый узел представляет собой комбинацию хэшей его дочерних элементов. Дерево Меркла простого проекта с четырьмя файлами выглядит так:

Пример хеш-дерева

  • Каждый файл получает хэш на основе его содержимого. Листьями дерева являются файлы.

  • Каждая папка получает хэш на основе хэша ее дочерних элементов.

Cursor использует похожий алгоритм, за исключением того, что он использует обфусцированные имена файлов. Клиент создает дерево на основе локальных файлов, а сервер создает его же, но на основе файлов, индексацию которых он завершил.

Каждые 3 минуты выполняется синхронизация индекса. Чтобы определить, какие файлы нуждаются в переиндексации, сравниваются два этих дерева:

Деревья на стороне клиента и сервера не синхронизированы.

Хеш-дерево легко обойти, потому что, начиная с корневого узла, нужно просто определять, совпадают ли хэши. Важно, что такое дерево минимизирует операции синхронизации только для тех файлов, которые изменились.

Безопасная индексация

Несмотря на то, что Cursor не хранит код на стороне сервера, существуют чувствительные части кодовой базы, которые не стоит отправлять, даже в зашифрованном виде. К ним относятся, например, ключи к API и пароли.

Использование .gitignore и .cursorignore — лучший способ обеспечить безопасность индексации. Секреты, ключи API, пароли и другая конфиденциальная информация не должны загружаться в систему контроля версий и обычно хранятся как локальные переменные или в локальных файлах окружения (.env файлах), которые добавляются в .gitignore. Cursor не будет индексировать файлы, указанные в .gitignore, а также не будет отправлять содержимое этих файлов на сервер. Кроме того, пользуйтесь файлом .cursorignore, куда следует добавлять файлы, которые должны игнорироваться при анализе кода.

Также перед загрузкой фрагментов для индексации Cursor также определяет, есть ли в куске кода секреты или конфиденциальные данные, и не отправляет их.

Индексация очень больших кодовых баз

Для огромных кодовых баз — монорепозиториев с десятками миллионов строк кода — индексация чрезвычайно трудоемка и в целом не нужна. Использование файла .cursorignore является разумным подходом в данном случае. Посмотрите советы в документации по этому поводу.

4. Anyrun: сервис-оркестратор Cursor

Anyrun — это название компонента-оркестратора, он полностью написан на Rust. «Anyrun» — это отсылка к названию компании Anysphere.

Anyrun отвечает за следующее:

Безопасный запуск AI-агентов в облаке. Всякий раз, когда вы запускаете задачу в Cursor через чат, агент начинает работать в облаке в фоновом режиме:

Когда вы даете инструкции в окне чата Cursor, агент начинает работать в облаке

Изоляция процессов. Агент, работающий в облаке, должен иметь доступ только к коду и контексту для текущего пользователя, который его запускает, и ни к чему больше. Anyrun использует разные подходы к изоляции в зависимости от клиента:

  • Виртуальные машины AWS EC2: используются для корпоративных клиентов. Этот подход предлагает полную изоляцию на уровне ВМ.

  • AWS Firecracker: легковесный подход к виртуализации, который использует микро-ВМ. Основное преимущество Firecracker — это время запуска: микро-ВМ запускается всего за 125 миллисекунд! (Ого! Прим. пер.)

Хотя Firecracker не имеет изоляции на уровне ВМ, AWS встроила несколько уровней защиты изоляции, минимизируя возможности атак.

Как работает Anyrun:

Основные функции оркестратора

Создание снапшотов — еще одна функция, которую поддерживает Anyrun; скоро появится фича по сохранению «снимка» вашего кода и создания «точку сохранения». При этом Anyrun сохранит текущее состояние ВМ. Позже пользователь сможет «отмотать» состояние до этой сохраненной точки. (Тут, видимо, речь идет о шагах, когда агент много раз что-то меняет и надо отмотать на середину его работы. Потому что коммитить мы и так умеем. Прим. пер.) В этом случае агент на Firecracker, должен перезапускаться менее чем за 150 мс.

Дальше рассмотрим инженерные вызовы и пару историй от разработчков.

Полная версия статьи находилась за paywall'ом, но автор любезно разрешил опубликовать полный перевод, за что ему спасибо! В этой части вроде ничего сложного нет, во второй будет поинтересней. Перевод второй части в процессе. Прим. пер.

Меня зовут Сергей, статьи на Хабр я пишу не часто, но часто пишу в телеграм-канал Градиент обреченный. Заходите в гости.

Комментарии (11)


  1. anavonmach
    20.06.2025 14:59

    Привет! Спаисбо.

    А если в проекте миллион файлов?


    1. averkij Автор
      20.06.2025 14:59

      Если у вас монорепа, то надо неиспользуемые подпроекты загнать в .cursorignore, иначе индексатор сдохнет. Хотя наверняка у них какие-нибудь таймауты стоят на этот случай.


      1. Akuma
        20.06.2025 14:59

        Он себя плохо чувствует и на 10 000 файлах, честно говоря. При том что ~8000 из них - это однотипные файлы-правила.

        А если монорепа на нес сколько языков, это вообще для него мрак


        1. averkij Автор
          20.06.2025 14:59

          Ну 10k файлов это многовато для одного проекта. Надо в .cursorignore закинуть.

          Начинаю себя чувствовать Cursor-евангелистом, хотя против Windsurf, Claude Code и других ничего не имею, кроме Codex, наверное.


          1. Akuma
            20.06.2025 14:59

            Не, это все один проект. Там правила парсинга для отдельных сайтов просто. Можно конечно вынести, но я не делаю. А если уж что-то начинает глючить (а оно периодически и внезапно начинает и не только ИИ), то решается уже по факту.

            В принципе, Курсору можно напрямую сказать что в этой папке много файлов, не читай ее целиком. И это работает.


  1. MountainGoat
    20.06.2025 14:59

    Пару часов пробовал Cursor IDE. Так и не понял, зачем он нужен. Все его ИИ возможности можно повторить в VSCode с дополнениями типа Windsurf. При этом в Cursor нет и не будет очень много, что реализовано в VSCode дополнениями.


    1. averkij Автор
      20.06.2025 14:59

      Так это же форк VS Code, туда можно дополнения ставить


      1. MountainGoat
        20.06.2025 14:59

        Только не все и не всегда. Некоторые нельзя по лицензии, другие просто не работают, а самые основные - и то, и другое.


    1. Akuma
      20.06.2025 14:59

      При том, что у Курсора такой себе агент (он сильно дешевле аналогов, но и тупее их), у них реально лучшее автодополнение, которое учится на лету. Оно понимает открытые файлы, оно понимает что вы только делали, а не просто повторяет одно и то же.

      $20 можно отдавать только за их автодополнение. Для написания кода, честно говоря, Cline/Roo куда лучше.


      1. averkij Автор
        20.06.2025 14:59

        По дополнению согласен, по-моему, он даже скопированный в буфер обмена код учитывает.


        1. Akuma
          20.06.2025 14:59

          Да, учитывает. Не раз замечал