инсайт этой недели по mongodb: сount is a blocking operation
под капотом count эквивалентен group+project:
а group aggregation имеет блокирующую природу:
под капотом count эквивалентен group+project:
db.collection.aggregate( [
{ $group: { _id: null, myCount: { $sum: 1 } } },
{ $project: { _id: 0 } }
] )
а group aggregation имеет блокирующую природу:
$group is a blocking stage, which causes the pipeline to wait for all input data to be retrieved for the blocking stage before processing the data. A blocking stage may reduce performance because it reduces parallel processing for a pipeline with multiple stages. A blocking stage may also use substantial amounts of memory for large data sets.
🤯2
Я много смотрю Theo и что мне нравится у него, так это обзор того, как он решает проблемы в своих продуктах
- https://www.youtube.com/watch?v=3gVBjTMS8FE: здесь он рассказывал, как перебирал БД к своему проекту (LLM wrapper) t3.chat (почему, какие проблемы были, как пришел к planetScale)
- https://www.youtube.com/watch?v=yXhbzFNUeh8: здесь он рассказывал, как проводил миграцию пользователей с MySQL -> Convex и почему у него трижды не получилось это сделать
- https://www.youtube.com/watch?v=3gVBjTMS8FE: здесь он рассказывал, как перебирал БД к своему проекту (LLM wrapper) t3.chat (почему, какие проблемы были, как пришел к planetScale)
- https://www.youtube.com/watch?v=yXhbzFNUeh8: здесь он рассказывал, как проводил миграцию пользователей с MySQL -> Convex и почему у него трижды не получилось это сделать
❤4
если кто-то платит за подписки на AI вот промо на t3.chat с разными моделями
Road to senior fullstack dev.
Vercel Fluid решал задачу в первую очередь под приложения, которым необходима обработка долгих запросов (любая обертка над LLM со стримом чанков на клиент) до этого мы последние 5 лет оптимизировали все вокруг response time / compute time: кеши, оптимизация…
case study судя по графику неплохой такой у них, интересно понаблюдать за развитием Fluid compute, совсем не тот serverless/lambda к которым мы привыкли с их проблемами (cold start + ненужный compute cost во время idle)
Forwarded from Стой под стрелой (Nikita Prokopov)
Очердной случай, когда самый умный и лучший оптимизатор PosgreSQL обосрался на ровном месте: запрос, выбирающий 2000 записей, выполняется за 0.3 секунды, а добавление к нему тривиального фильтра (одна из колонок равна константе) увеличивает время выполнения до 20 секунд. В 66 раз! Братан, я вручную 2000 записей быстрее проверю.
В этом проблема с высокоуровневыми инструментами: пока ты от них многого не требуешь и разбираться не хочешь, они как будто помогают. Но как только ты начинаешь их серьезно использовать, сразу выясняется что вся эта декларативщина только мешает: я руками быстрее, короче и понятнее бы план написал, и работал бы он всегда, а не по настроению. Это другой мем: тот самый запрос на 20 секунд начал выполняться нормально спустя пару часов — что-то там в мозгах у Постгреса перещелкнуло. Ну и как на такое полагаться?
Обещания: просто пишите запросы, и вам не нужно будет думать. Реальность: приходится думать, как бы из «умного» Постгреса сделать тупой.
В этом проблема с высокоуровневыми инструментами: пока ты от них многого не требуешь и разбираться не хочешь, они как будто помогают. Но как только ты начинаешь их серьезно использовать, сразу выясняется что вся эта декларативщина только мешает: я руками быстрее, короче и понятнее бы план написал, и работал бы он всегда, а не по настроению. Это другой мем: тот самый запрос на 20 секунд начал выполняться нормально спустя пару часов — что-то там в мозгах у Постгреса перещелкнуло. Ну и как на такое полагаться?
Обещания: просто пишите запросы, и вам не нужно будет думать. Реальность: приходится думать, как бы из «умного» Постгреса сделать тупой.
Forwarded from Dev Easy Notes
Ну что ребятки, финалим эту серию про CI, какие задачи лучше не делать в CI.
Присаживайтесь поудобнее мы погружаемся в инфраструктурный хардкор.
Лакмусовой бумажкой того, что задаче не место в CI — если в Job не нужно получать последнюю версию кода. Если для ускорения выполнения Job вы хотите отключить клонирование мастера, задачу точно нужно выносить в другую систему.
Например вы хотите пинговать разработчика, если у него упал пайплайн на МРе. Это не CI-задача, и нет смысла занимать под неё целый runner.
В идеале я бы советовал развернуть на серверах компании какой-нибудь n8n. Вы тогда получаете гибкий инструмент в котором можете развлекаться как хотите без влияния на пайплайны.
Требуется гибкая логика повторных запусков. В Gitlab и похожих системах есть retry, но весьма тупой. Он не позволяет задать условия повторного запуска, основанные на типах ошибок или внешнем состоянии.
Нельзя например сказать: «Повтори, если ошибка 500», «Повтори с экспоненциальной задержкой».
В этом случае лучше подойдут системы c возможностью описывать, при каких условиях и сколько раз нужно повторять шаг вроде Airflow, Prefect или Temporal.
Вас не устраивает линейная структура. Если у вас возникает желание, ах вот если бы сюда поставить if или какой-нибудь while, то это явно не про CI. Платформы вроде GitLab CI поддерживают только линейное выполнение без предусловий. Airflow, Prefect и Dagster позволяют описывать не только последовательность действий, но и условия, при которых они должны выполняться.
Вам нужен гибкий cron с историй запусков. В CI системах есть примитивный cron вроде: «запускай вот этот пайплайн каждый день в 12 ночи». Однако в задачах вроде дообучения моделей или каких-то бизнес процессах могут возникнуть потребность: «выполнять cron только по будням», «пропускать запуск, если нет входных данных», «догнать пропущенные даты если была ошибка».
Помимо этого в Gitlab CI еще и историю запусков по cron нельзя просмотреть, показывается только последний запуск, а этого может быть мало.
Пайплайн должен реагировать на внешнее событие. Поступление файла, вебхук, изменение записи в базе — CI не предназначен для этого. Он реагирует только на изменения в коде или cron.
Если логика основана на событиях извне, её проще и надёжнее реализовать в n8n или Prefect, где предусмотрены подписки на события, задержки и отложенные действия.
Подводя итог: CI нужен для тестов, сборок и деплоя. Всё, что выходит за рамки «выполни скрипт и проверь результат», особенно если это связано со временем, входными данными, внешними событиями или сложными зависимостями — должно выполняться в отдельных специализированых системах.
Если же данный пост показался вам слишком перегруженным и вы потерялись в названии кучи сервисов записывайтесь на мой авторский курс «Батя инфры» на котором я научу вас работать с данными системами и зарабатывать миллионы.
Присаживайтесь поудобнее мы погружаемся в инфраструктурный хардкор.
Лакмусовой бумажкой того, что задаче не место в CI — если в Job не нужно получать последнюю версию кода. Если для ускорения выполнения Job вы хотите отключить клонирование мастера, задачу точно нужно выносить в другую систему.
Например вы хотите пинговать разработчика, если у него упал пайплайн на МРе. Это не CI-задача, и нет смысла занимать под неё целый runner.
В идеале я бы советовал развернуть на серверах компании какой-нибудь n8n. Вы тогда получаете гибкий инструмент в котором можете развлекаться как хотите без влияния на пайплайны.
Требуется гибкая логика повторных запусков. В Gitlab и похожих системах есть retry, но весьма тупой. Он не позволяет задать условия повторного запуска, основанные на типах ошибок или внешнем состоянии.
Нельзя например сказать: «Повтори, если ошибка 500», «Повтори с экспоненциальной задержкой».
В этом случае лучше подойдут системы c возможностью описывать, при каких условиях и сколько раз нужно повторять шаг вроде Airflow, Prefect или Temporal.
Вас не устраивает линейная структура. Если у вас возникает желание, ах вот если бы сюда поставить if или какой-нибудь while, то это явно не про CI. Платформы вроде GitLab CI поддерживают только линейное выполнение без предусловий. Airflow, Prefect и Dagster позволяют описывать не только последовательность действий, но и условия, при которых они должны выполняться.
Вам нужен гибкий cron с историй запусков. В CI системах есть примитивный cron вроде: «запускай вот этот пайплайн каждый день в 12 ночи». Однако в задачах вроде дообучения моделей или каких-то бизнес процессах могут возникнуть потребность: «выполнять cron только по будням», «пропускать запуск, если нет входных данных», «догнать пропущенные даты если была ошибка».
Помимо этого в Gitlab CI еще и историю запусков по cron нельзя просмотреть, показывается только последний запуск, а этого может быть мало.
Пайплайн должен реагировать на внешнее событие. Поступление файла, вебхук, изменение записи в базе — CI не предназначен для этого. Он реагирует только на изменения в коде или cron.
Если логика основана на событиях извне, её проще и надёжнее реализовать в n8n или Prefect, где предусмотрены подписки на события, задержки и отложенные действия.
Подводя итог: CI нужен для тестов, сборок и деплоя. Всё, что выходит за рамки «выполни скрипт и проверь результат», особенно если это связано со временем, входными данными, внешними событиями или сложными зависимостями — должно выполняться в отдельных специализированых системах.
Если же данный пост показался вам слишком перегруженным и вы потерялись в названии кучи сервисов записывайтесь на мой авторский курс «Батя инфры» на котором я научу вас работать с данными системами и зарабатывать миллионы.
Fluid Compute vs Serverless vs Dedicated Server, Vercel Ship, Active CPU Pricing
Раз уж вышла целая куча апдейтов от Vercel (теперь понятно почему они назвали ивент Ship), то разберем более детально отличия Fluid Compute от привычного serverless/lambda
Откуда вообще пошел тренд что-то менять в устоявшейся технологии?
Ну, во-первых, надо искать инвесторов, маркетинг должен на чем-то кликбейтить, поэтому держите список фичей флюида по сравнению с обычными serverless
Отсюда и видны основные минусы серверлесса, разницу серверлесса над dedicated сервером описывал тут, но если еще раз и кратко, то сервер надо поддерживать, обеспечивать ресурсами под ожидаемую нагрузку (учитывая пики, учитывая некоторую флуктуацию, учитывая маркетинг), а это инфра. В то же время айдл серверлесса тоже обходится в лишнюю копейку, нет конкаренси, зато не надо париться с масштабированием. Так же надо учитывать, что серверлесс изолирован и у него есть трейд-оффы: singe-purpose, short-lived, cold starts, underutilized compute (компании платят за неиспользуемые ресурсы)
Во-вторых, мы живем с вами в эпоху AI, так что мы так или иначе убираемся в I/O bound логику для AI зависимых приложений -
Поэтому Vercel сделал ставку на комбинированный подход: эффективность сервера с масштабируемостью серверлесса.
Но действительно ли Fluid Compute так хорош, если у вас не I/O bound? или нет сильной необходимости в канкаренси?
Несмотря на то, что Fluid открыл возможность для оптимизации перформанса и бюджета, изъяны все равно можно найти:
эту проблему как раз решает анонсированный Active CPU pricing:
Раз уж вышла целая куча апдейтов от Vercel (теперь понятно почему они назвали ивент Ship), то разберем более детально отличия Fluid Compute от привычного serverless/lambda
Откуда вообще пошел тренд что-то менять в устоявшейся технологии?
Ну, во-первых, надо искать инвесторов, маркетинг должен на чем-то кликбейтить, поэтому держите список фичей флюида по сравнению с обычными serverless
Optimized concurrency: Functions can handle multiple requests per instance, reducing idle time and lowering compute costs by up to 85% for high-concurrency workloads
Cold start protection: Fewer cold starts with smarter scaling and pre-warmed instances
Optimized scaling: Functions scale before instances, moving beyond the traditional 1:1 invocation-to-instance model
Extended function lifecycle: Use waitUntil to run background tasks after responding to the client
Runaway cost protection: Detects and stops infinite loops and excessive invocations
Multi-region execution: Requests are routed to the nearest of your selected compute region for better performance
Node.js and Python support: No restrictions on native modules or standard libraries
Отсюда и видны основные минусы серверлесса, разницу серверлесса над dedicated сервером описывал тут, но если еще раз и кратко, то сервер надо поддерживать, обеспечивать ресурсами под ожидаемую нагрузку (учитывая пики, учитывая некоторую флуктуацию, учитывая маркетинг), а это инфра. В то же время айдл серверлесса тоже обходится в лишнюю копейку, нет конкаренси, зато не надо париться с масштабированием. Так же надо учитывать, что серверлесс изолирован и у него есть трейд-оффы: singe-purpose, short-lived, cold starts, underutilized compute (компании платят за неиспользуемые ресурсы)
Во-вторых, мы живем с вами в эпоху AI, так что мы так или иначе убираемся в I/O bound логику для AI зависимых приложений -
I/O bound backends like AI inference, agents, MCP servers, and anything that needs to scale instantly, but often remains idle between operations. These workloads do not follow traditional, quick request-response patterns. They’re long-running, unpredictable, and use cloud resources in new ways.
I/O-bound refers to a process that is limited by input/output operations rather than CPU speed. These tasks spend most of their time waiting for external resources, such as database queries, API requests, or file system operations, rather than performing computations. Optimizing I/O-bound tasks often involves concurrency to maximize resource efficiency.
Поэтому Vercel сделал ставку на комбинированный подход: эффективность сервера с масштабируемостью серверлесса.
Instead of spinning up a separate instance for each invocation, Fluid compute intelligently orchestrates compute across invocations. Multiple concurrent requests can share the same underlying resources, eliminating cold starts and reusing idle time. This allows I/O bound workloads like AI to run more efficiently.
Но действительно ли Fluid Compute так хорош, если у вас не I/O bound? или нет сильной необходимости в канкаренси?
Несмотря на то, что Fluid открыл возможность для оптимизации перформанса и бюджета, изъяны все равно можно найти:
Even with high concurrency, there could still be moments where all invocations are waiting on external responses and no code is actively running. During these idle periods, functions stay in memory, doing no work, yet still incur CPU cost.
эту проблему как раз решает анонсированный Active CPU pricing:
It's a new pricing model that charges for CPU only when your code is actively using the CPU.
🔥3
Yet another serverless workflow on Vercel или причины по которым Vercel открывает новую модель биллинга - Active CPU Billing
продолжаем серию постов с разбором полетов нововведений пришедших с Vercel Ship, в прошлый раз мы разобрали Fluid Compute, его отличия от Serverless и Dedicated Server и теперь у нас есть опорная точка для сравнения и понимания новой модели, откуда растут ноги и что нам, разработчикам, с этим делать
чтобы чуть лучше понять причину изменения системы биллинга, надо сначала поговорить про Cloudflare Workers, их отличия от AWS Lambda и Vercel Serverless (Fluid Compute и обычный)
представим, что вы сели сегодня разрабатывать AI wrapper, вы не хотите заниматься overprovisioning-ом и масштабированием dedicated server-a, поэтому выбор пал на serverless, осталось определить вендора. Но чтобы выбрать вендора, надо понять как они работают, чтобы хоть как-то прицениться к чеку на текущую/будущую нагрузку на наш сервис. Пойдем разбираться
Итого, кто у нас есть:
Что есть у CF Workers - очень низкий CPU perf. Есть ограничения на память (как бинарника 10мб, так и серверлесс инстанса 128мб). CF Workers хорошо подходит под задачи обработки входящих запросов, с их модификацией и направлением в нужные места, а-ля advanced switch statement. Он исторически плохо справляется с задачами SSR по тем же самым причинам (CPU Bound). Абстракция на уровне V8 engine, а не над ядром (kernel), shared event loop. Из-за этого на одной поднятой машине может изолированно исполняться разный код: и ваш, и чужой. Эта модель позволяет им делать справедливо низкий чек, они тарифицируют за invocations + Net CPU и само CPU у них на 50% дешевле нынешней Vercel + Active CPU billing. Совместимость с Node.js практически нулевая, вы очень ограничены если не используете CF Containers, никакой ffmpeg в WASM у вас не поедет там хорошо. Хорошая Node.js COMPAT есть в Vercel
AWS Lambda/Vercel - way faster CPU, у AWS Lambda есть возможность предоставления доп ресурсов на серверлесс инстанс, у Vercel есть тоже CPU Allocation.
Возвращаемся к нашему приложению, для простоты рассмотрим только 2 ендпоинта: получение данных (существующие чаты), чат (запрос в ЛЛМ). Первый тип общения с БД и возвратом ответа ложится идеально в концепцую Serverless, масштабирование по нагрузке, вам не надо держать доп ресурсы на внезапные пики, переплачивать за это или настраивать сложную систему автомасштабирования. Запросы будут выполняться 100-300мс, и вам в целом ок, что там есть idle, даже если 10-15% этого процесса исполняется на CPU
Любой из запросов можно изобразить так, разница будет в долях total CPU/total idle:
Хорошо, если во время idle окна у вас есть нагрузка и запросы других юзеров могут исполняться тем же инстансом, но тем не менее, чек придет за все суммарное окно всех запросов.
В случае общения с ЛЛМ ситуация меняется в корне, некоторые модели, такие как o3-pro, могут генерировать ответ минуты или даже десятки минут. Так, если у вас было 100 последовательных запросов, которые заняли окно в 80 секунд, притом что общее время работы CPU 5ms, используя разные модели, вас по разному тарифицируют:
Именно в таком флоу разница колоссальна!
продолжаем серию постов с разбором полетов нововведений пришедших с Vercel Ship, в прошлый раз мы разобрали Fluid Compute, его отличия от Serverless и Dedicated Server и теперь у нас есть опорная точка для сравнения и понимания новой модели, откуда растут ноги и что нам, разработчикам, с этим делать
чтобы чуть лучше понять причину изменения системы биллинга, надо сначала поговорить про Cloudflare Workers, их отличия от AWS Lambda и Vercel Serverless (Fluid Compute и обычный)
представим, что вы сели сегодня разрабатывать AI wrapper, вы не хотите заниматься overprovisioning-ом и масштабированием dedicated server-a, поэтому выбор пал на serverless, осталось определить вендора. Но чтобы выбрать вендора, надо понять как они работают, чтобы хоть как-то прицениться к чеку на текущую/будущую нагрузку на наш сервис. Пойдем разбираться
Итого, кто у нас есть:
- CF Workers
- AWS Lambda
- Vercel Serverless
- Vercel Serverless server (Fluid Compute) w/o Active CPU Billing
- Vercel Serverless server (Fluid Compute) with Active CPU Billing
Что есть у CF Workers - очень низкий CPU perf. Есть ограничения на память (как бинарника 10мб, так и серверлесс инстанса 128мб). CF Workers хорошо подходит под задачи обработки входящих запросов, с их модификацией и направлением в нужные места, а-ля advanced switch statement. Он исторически плохо справляется с задачами SSR по тем же самым причинам (CPU Bound). Абстракция на уровне V8 engine, а не над ядром (kernel), shared event loop. Из-за этого на одной поднятой машине может изолированно исполняться разный код: и ваш, и чужой. Эта модель позволяет им делать справедливо низкий чек, они тарифицируют за invocations + Net CPU и само CPU у них на 50% дешевле нынешней Vercel + Active CPU billing. Совместимость с Node.js практически нулевая, вы очень ограничены если не используете CF Containers, никакой ffmpeg в WASM у вас не поедет там хорошо. Хорошая Node.js COMPAT есть в Vercel
AWS Lambda/Vercel - way faster CPU, у AWS Lambda есть возможность предоставления доп ресурсов на серверлесс инстанс, у Vercel есть тоже CPU Allocation.
Возвращаемся к нашему приложению, для простоты рассмотрим только 2 ендпоинта: получение данных (существующие чаты), чат (запрос в ЛЛМ). Первый тип общения с БД и возвратом ответа ложится идеально в концепцую Serverless, масштабирование по нагрузке, вам не надо держать доп ресурсы на внезапные пики, переплачивать за это или настраивать сложную систему автомасштабирования. Запросы будут выполняться 100-300мс, и вам в целом ок, что там есть idle, даже если 10-15% этого процесса исполняется на CPU
Любой из запросов можно изобразить так, разница будет в долях total CPU/total idle:
- [CPU] верификация юзера + проверки доступов
- [idle] ожидания ответа из бд / inference
- [CPU] трансформация ответа из бд и подготовка ответа клиенту (либо рендер html из json)
Хорошо, если во время idle окна у вас есть нагрузка и запросы других юзеров могут исполняться тем же инстансом, но тем не менее, чек придет за все суммарное окно всех запросов.
В случае общения с ЛЛМ ситуация меняется в корне, некоторые модели, такие как o3-pro, могут генерировать ответ минуты или даже десятки минут. Так, если у вас было 100 последовательных запросов, которые заняли окно в 80 секунд, притом что общее время работы CPU 5ms, используя разные модели, вас по разному тарифицируют:
Serverless: 80s * 100 = 8000s
Fluid: 80s * 1 req = 80s
Net CPU: 5ms*100 req = 500ms = 0.5s
Именно в таком флоу разница колоссальна!
❤2
Road to senior fullstack dev.
Yet another serverless workflow on Vercel или причины по которым Vercel открывает новую модель биллинга - Active CPU Billing продолжаем серию постов с разбором полетов нововведений пришедших с Vercel Ship, в прошлый раз мы разобрали Fluid Compute, его отличия…
Теперь становится понятно, Vercel решил поджать под себя AI индустрию, так как, наверняка, многие кто пробовал хостить у них такие задачи жаловались на несправедливые чеки, учитывая что 90% времени все твои функции в состоянии idle.
И если раньше, перенос Vercel -> CF Workers мог привнести большой бенефит по срезанию чека (до сотни раз больше приходилось платить за версель), то сейчас это значение снивелировало до примерно 2. Да, вы все еще платите за версель больше, но получаете более мощное cpu + node compat
единственно, что меня прям смущает, так это то, что они не сделали копию CF Workers, у них абстракция на разных уровнях, они сейчас включили Active CPU Billing всем по-дефолту. Это приведет однозначно к уменьшению доходов компании. Я не знаю какая у них бизнес экономика, может они свою инфру тоже сильно этим порежут (они же aws wrapper?), может это очередная прикормка для инвесторов, чтобы перетянуть долю рынка со всех AI бизнесов поработав какое-то время в убыток, чтобы залочить их, кто знает. Но СF Workers действительно может себе такое позволять, потому что на его раскрученном инстансе может испольняться не только ваш код в idle, они вообще, наверное, не простаивают:
И если раньше, перенос Vercel -> CF Workers мог привнести большой бенефит по срезанию чека (до сотни раз больше приходилось платить за версель), то сейчас это значение снивелировало до примерно 2. Да, вы все еще платите за версель больше, но получаете более мощное cpu + node compat
единственно, что меня прям смущает, так это то, что они не сделали копию CF Workers, у них абстракция на разных уровнях, они сейчас включили Active CPU Billing всем по-дефолту. Это приведет однозначно к уменьшению доходов компании. Я не знаю какая у них бизнес экономика, может они свою инфру тоже сильно этим порежут (они же aws wrapper?), может это очередная прикормка для инвесторов, чтобы перетянуть долю рынка со всех AI бизнесов поработав какое-то время в убыток, чтобы залочить их, кто знает. Но СF Workers действительно может себе такое позволять, потому что на его раскрученном инстансе может испольняться не только ваш код в idle, они вообще, наверное, не простаивают:
Fluid Compute (serverless servers) = one node that can resolve multiple users requests but only has one binary (one piece of code running on it)
Cloudflare solution = lots of different developers codes running on the same box at the same time (abstracting per function call level)
Cегодня поговорим про BotID представленный на Vercel Ship, но чтобы его оценить по достоинству, надо снова опираться от чего-то что есть на рынке
Задача очевидная, ограничивать доступ к сервису от ботов/экспойлтов злоумышленников, во-первых, потому что это DDoS/нагрузка на ваши сервисы, что может приводить к недоступности сервисов, во вторых это может стоить вам денег (если опять говорим про какие-нибудь задачи inference = LLM)
Попробуем поискать на рынке топ капча сервис, что он должен включать?
Captcha Killer
- A GOOD INVISIBLE MODE + Promotion to visible captcha on fail (мы не хотим чтобы юзеры на каждый верификационный реквест решали капчу, хотим чтобы основные проверки проходили фоном, и если такие проверки были неудачными, мы получали уже реальный челлендж для решения)
- Low false positives (мы не хотим блокировать реальным пользователям доступ к платформе)
- Good DX (хотим коробочное решение, которое не требует больших усилий по интеграции и гадании на картах таро по документации о том как это все работает), an npm package that knows what React is, typesafety
- Different error states handled (хотим по-разному реагировать на ошибки, как минимум для мониторинга, чтобы знать, когда чел не прошел верификацию и почему, сломался он на инвизибл проверке, не захотел решать челлендж и тд)
Теперь смотрим на рынок:
- Cloudflare Turnstile
- Google Recaptcha v3
- hcaptcha
Теперь посмотрим что они предлагают, чтобы удовлетворить наши фичи:
upd: если у кого поехала таблица, смотрим в комменты
| Feature | Turnstile | Recaptcha v3 | hCaptcha |
| :---------------------------- | :-------- | :----------- | :------- |
| Ease of integration | 5/10 | 3/10 | 6/10 |
| Invisible mode reliability | 0/10 | 4/10 | 9/10 |
| Cost | 10/10 | 4/10 | 3/10 |
| Documentation | 4/10 | 1/10 | 7/10 |
| Testability in dev | 5/10 | 2/10 | 4/10 |
| Support for "promote from inv" | 0/10 | 0/10 | 10/10 |
Так что же из себя представляет Vercel BotID? Очередной убийца CF Turnstile? Выглядит как да, явно будет меньше false positive cрабатываний, интеграция из коробки.
Единственное, чего мне не хватило в текущей имплементации Vercel BotID, у вас только 1 тип интеграции на уровне проекта: Basic / Deep Analysis. Но хочется иметь в проекте сразу два типа, basic - везде, deep analysis на критически важные клиентские пути (чтобы задавалось на уровне конфига). Думаю это скоро поправят. А может это очередной лок на выкачивание денег
Задача очевидная, ограничивать доступ к сервису от ботов/экспойлтов злоумышленников, во-первых, потому что это DDoS/нагрузка на ваши сервисы, что может приводить к недоступности сервисов, во вторых это может стоить вам денег (если опять говорим про какие-нибудь задачи inference = LLM)
Попробуем поискать на рынке топ капча сервис, что он должен включать?
Captcha Killer
- A GOOD INVISIBLE MODE + Promotion to visible captcha on fail (мы не хотим чтобы юзеры на каждый верификационный реквест решали капчу, хотим чтобы основные проверки проходили фоном, и если такие проверки были неудачными, мы получали уже реальный челлендж для решения)
- Low false positives (мы не хотим блокировать реальным пользователям доступ к платформе)
- Good DX (хотим коробочное решение, которое не требует больших усилий по интеграции и гадании на картах таро по документации о том как это все работает), an npm package that knows what React is, typesafety
- Different error states handled (хотим по-разному реагировать на ошибки, как минимум для мониторинга, чтобы знать, когда чел не прошел верификацию и почему, сломался он на инвизибл проверке, не захотел решать челлендж и тд)
Теперь смотрим на рынок:
- Cloudflare Turnstile
- Google Recaptcha v3
- hcaptcha
Теперь посмотрим что они предлагают, чтобы удовлетворить наши фичи:
upd: если у кого поехала таблица, смотрим в комменты
| Feature | Turnstile | Recaptcha v3 | hCaptcha |
| :---------------------------- | :-------- | :----------- | :------- |
| Ease of integration | 5/10 | 3/10 | 6/10 |
| Invisible mode reliability | 0/10 | 4/10 | 9/10 |
| Cost | 10/10 | 4/10 | 3/10 |
| Documentation | 4/10 | 1/10 | 7/10 |
| Testability in dev | 5/10 | 2/10 | 4/10 |
| Support for "promote from inv" | 0/10 | 0/10 | 10/10 |
Так что же из себя представляет Vercel BotID? Очередной убийца CF Turnstile? Выглядит как да, явно будет меньше false positive cрабатываний, интеграция из коробки.
Единственное, чего мне не хватило в текущей имплементации Vercel BotID, у вас только 1 тип интеграции на уровне проекта: Basic / Deep Analysis. Но хочется иметь в проекте сразу два типа, basic - везде, deep analysis на критически важные клиентские пути (чтобы задавалось на уровне конфига). Думаю это скоро поправят. А может это очередной лок на выкачивание денег
Media is too big
VIEW IN TELEGRAM
PlanetScale now supports Postgres.
Forwarded from запуск завтра
Как перезапустить проект технически?
Прямо сейчас мы решаем эту задачу для стартапа. Ребята делают платформу для ученых, чтобы проводить исследования на больших группах респондентов. Куча интеграций, огромный зоопарк форматов данных.
Они пользуются уже третьей версией своей платформы. Фронтенд на low-code платформе Bubble, бэкенд частично на flask и частично n8n. Всё работает, приносит пользу, проект поднял больше миллиона долларов инвестиций.
Как навести порядок, радикально увеличить скорость доставки фич и гарантировать масштабируемость?
Первый порыв любого программиста — переписать всё с нуля. Благо, проект ещё не очень большой, за месяца 3–4 парой программистов, наверное, можно управиться. Составить список фичей, написать их заново, потушить сервис на пару часов, импортировать данные из старой системы в новую и запуститься.
Но это — ошибка. Во-первых, мы не понимаем истинного объема бизнес-логики, который успел накопиться в коде. Скорее всего, сам клиент её недооценивает. Во-вторых, пока будем переписывать — проект продолжит развиваться. Придется догонять. В-третьих, любой, кто делал импорт данных, скажет вам, что это задача из ада, и чем старее данные — тем сложнее их вытащить. Настроить тестирование этого нового проекта будет сложно, да и полноценным оно не может быть по определению.
В результате, в момент включения новой платформы в продакшен, точно возникнут проблемы, которые придется героически исправлять «прямо сейчас», в стрессе. Мало предсказуемости, о реальном объеме работы мы узнаем только в самом конце проекта, при попытке переключения. Мы такое не любим.
Правильный ход — это strangler fig pattern. Пишем небольшую обертку для старого бэкенда. Этот новый бэкенд действует как прокси — передает запросы к старому бэкенду, запоминая сами запросы и ответы. Дальше выделяем первые эндпоинты бэкенда, которые мы можем запрограммировать заново, красиво. Дублируем эти запросы пользователей в старый и новые движки. Сравниваем ответы нового движка с ответами старого, исправляем ошибки. Накапливаем информацию в новую, аккуратно составленную базу данных. И только после продолжительного тестирования на живых данных начинаем отдавать пользователю ответы нового бэкенда. Берем следующую пачку эндпоинтов и повторяем процесс.
Получается, у нас нет момента «большого рубильника», который переключит весь трафик со старого движка на новый, мы «едим этого слона по частям». Переход со старого бэкенда на новый происходит плавно, незаметно для бизнеса. Ошибки в новой системе видны только программистам и не затрагивают клиентов.
Не менее важна предсказуемость. В первом подходе мы весь проект живем под дамокловым мечом — какие сюрпризы нас ждут при запуске? Во втором подходе мы размазываем эту неопределенность по всей продолжительности проекта, так что уже через пару недель можно увидеть реальную скорость разработки, включая исправление ошибок, и оценить общий объем работы и сроки.
Наконец, этот подход позволяет выкатывать новые фичи в продукте внутри нового бэкенда до окончания переезда, параллельно с рефакторингом.
К сожалению, кажется, что каждый молодой программист обречен пытаться всё переписать правильно с нуля. Технарь, предлагающий strangler fig pattern, не лучше, просто за его обучение уже заплатил другой заказчик.
На фотографии тот самый фикус-душитель опутывает дерево, как новый бэкенд опутывает старый.
Прямо сейчас мы решаем эту задачу для стартапа. Ребята делают платформу для ученых, чтобы проводить исследования на больших группах респондентов. Куча интеграций, огромный зоопарк форматов данных.
Они пользуются уже третьей версией своей платформы. Фронтенд на low-code платформе Bubble, бэкенд частично на flask и частично n8n. Всё работает, приносит пользу, проект поднял больше миллиона долларов инвестиций.
Как навести порядок, радикально увеличить скорость доставки фич и гарантировать масштабируемость?
Первый порыв любого программиста — переписать всё с нуля. Благо, проект ещё не очень большой, за месяца 3–4 парой программистов, наверное, можно управиться. Составить список фичей, написать их заново, потушить сервис на пару часов, импортировать данные из старой системы в новую и запуститься.
Но это — ошибка. Во-первых, мы не понимаем истинного объема бизнес-логики, который успел накопиться в коде. Скорее всего, сам клиент её недооценивает. Во-вторых, пока будем переписывать — проект продолжит развиваться. Придется догонять. В-третьих, любой, кто делал импорт данных, скажет вам, что это задача из ада, и чем старее данные — тем сложнее их вытащить. Настроить тестирование этого нового проекта будет сложно, да и полноценным оно не может быть по определению.
В результате, в момент включения новой платформы в продакшен, точно возникнут проблемы, которые придется героически исправлять «прямо сейчас», в стрессе. Мало предсказуемости, о реальном объеме работы мы узнаем только в самом конце проекта, при попытке переключения. Мы такое не любим.
Правильный ход — это strangler fig pattern. Пишем небольшую обертку для старого бэкенда. Этот новый бэкенд действует как прокси — передает запросы к старому бэкенду, запоминая сами запросы и ответы. Дальше выделяем первые эндпоинты бэкенда, которые мы можем запрограммировать заново, красиво. Дублируем эти запросы пользователей в старый и новые движки. Сравниваем ответы нового движка с ответами старого, исправляем ошибки. Накапливаем информацию в новую, аккуратно составленную базу данных. И только после продолжительного тестирования на живых данных начинаем отдавать пользователю ответы нового бэкенда. Берем следующую пачку эндпоинтов и повторяем процесс.
Получается, у нас нет момента «большого рубильника», который переключит весь трафик со старого движка на новый, мы «едим этого слона по частям». Переход со старого бэкенда на новый происходит плавно, незаметно для бизнеса. Ошибки в новой системе видны только программистам и не затрагивают клиентов.
Не менее важна предсказуемость. В первом подходе мы весь проект живем под дамокловым мечом — какие сюрпризы нас ждут при запуске? Во втором подходе мы размазываем эту неопределенность по всей продолжительности проекта, так что уже через пару недель можно увидеть реальную скорость разработки, включая исправление ошибок, и оценить общий объем работы и сроки.
Наконец, этот подход позволяет выкатывать новые фичи в продукте внутри нового бэкенда до окончания переезда, параллельно с рефакторингом.
К сожалению, кажется, что каждый молодой программист обречен пытаться всё переписать правильно с нуля. Технарь, предлагающий strangler fig pattern, не лучше, просто за его обучение уже заплатил другой заказчик.
На фотографии тот самый фикус-душитель опутывает дерево, как новый бэкенд опутывает старый.
❤3👍1
сегодня внесли небольшое с точки зрения кода улучшение, но имеющее невероятную ценность в дистанции (ака scalability и поддержка)
пришло требования организовать следующую бизнес логику:
- по UPI (читай id/urn) получить айди интеграций из сервиса А, затем по этим идентификаторам забрать сами интеграции из сервиса Б
варианты реализации:
1) 2 раунд трипа с фронта, сходить в один сервис, затем сходить в другой.
из плюсов, бекенд можно оставить as is
из минусов - двойной заход по сети, когда данные можно отдать одним запросом, в идеале еще и агрегацией на уровне бд, а не имплементацией двух запросов в разные коллекции
2) DI одного сервиса в другой, чтобы иметь возможность дернуть существующую БЛ вокруг получения некоторого интерфейса.
Плюсы: изменения связанные с обновлением БЛ локализованы в одной точке, цена поддержки 1х
минусы: сервис Б может быть раздутым (как у нас и случилось), с точки зрения композиции не понятно, почему сервису А нужен сервис Б, циклические зависимости
3) дублирование реализации получения сущности интеграции по айди в сервисе А
Плюсы: сервис Б больше не имеет прямую связь с сервисом А и может существовать независимо
минусы: очередной low-level mongoose pipeline на уровне DAL, очередной cross platform interface (IIntegrationPopulatedV1, IIntegrationPopulatedV2, IIntegrationPopulatedV3) - какой выбирать? поддержка 2х
Что с этим сделали?
Решили внедрять вертикальные слайсы, продукт стартап, команда растет, обычной горизонтальной нарезки коллекций на controller/module/service уже недостаточно, в идеале все взаимодействие с БД выносить в DAL (ооп-лайк подход, который будет инкапсулировать все взаимодействие и отличать общение с БД от БизнесЛогики). Вертикальный слайс дробит продукт на фичи. Теперь фича является холдером горизонтальных слайсов, определяем фичу, нарезаем под нее именованный сервис, в него уже инжектим composable части.
Нашли подход позволяющий скейлить и шерить логику на бекенде бесконечно, но это в теории, понаблюдаем, как это будет развиваться со временем, люблю рефлексировать над подобным опытом со временем
пришло требования организовать следующую бизнес логику:
- по UPI (читай id/urn) получить айди интеграций из сервиса А, затем по этим идентификаторам забрать сами интеграции из сервиса Б
варианты реализации:
1) 2 раунд трипа с фронта, сходить в один сервис, затем сходить в другой.
из плюсов, бекенд можно оставить as is
из минусов - двойной заход по сети, когда данные можно отдать одним запросом, в идеале еще и агрегацией на уровне бд, а не имплементацией двух запросов в разные коллекции
2) DI одного сервиса в другой, чтобы иметь возможность дернуть существующую БЛ вокруг получения некоторого интерфейса.
Плюсы: изменения связанные с обновлением БЛ локализованы в одной точке, цена поддержки 1х
минусы: сервис Б может быть раздутым (как у нас и случилось), с точки зрения композиции не понятно, почему сервису А нужен сервис Б, циклические зависимости
3) дублирование реализации получения сущности интеграции по айди в сервисе А
Плюсы: сервис Б больше не имеет прямую связь с сервисом А и может существовать независимо
минусы: очередной low-level mongoose pipeline на уровне DAL, очередной cross platform interface (IIntegrationPopulatedV1, IIntegrationPopulatedV2, IIntegrationPopulatedV3) - какой выбирать? поддержка 2х
Что с этим сделали?
Решили внедрять вертикальные слайсы, продукт стартап, команда растет, обычной горизонтальной нарезки коллекций на controller/module/service уже недостаточно, в идеале все взаимодействие с БД выносить в DAL (ооп-лайк подход, который будет инкапсулировать все взаимодействие и отличать общение с БД от БизнесЛогики). Вертикальный слайс дробит продукт на фичи. Теперь фича является холдером горизонтальных слайсов, определяем фичу, нарезаем под нее именованный сервис, в него уже инжектим composable части.
Нашли подход позволяющий скейлить и шерить логику на бекенде бесконечно, но это в теории, понаблюдаем, как это будет развиваться со временем, люблю рефлексировать над подобным опытом со временем
Forwarded from DevFM
Cursor изнутри
Недавно вышла немного рекламная, но легкая и интересная статья от The Pragmatic Engineer о том, как устроен Cursor узнутри.
В начале статьи просто любопытные цифры о Cursor. Дальше автор рассказывает нам о технологическом стеке. Из интересного:
- TypeScript – бизнес-логика, критические штуки на Rust
- Turbopuffer – основное KV-хранилище, держит зашифрованные файлы + Merkle-деревья для синка
- Pinecone – векторная БД для семантического поиска по коду
- Datadog, PagerDuty, Sentry, Amplitude для обзервабилити
- Linear – для таск трекинга (рекомендую попробовать для тех, кто не пробовал, интересное решение)
Cursor не хранит наш код на своих серверах. Когда вы отправляете запрос в Chat, происходит следующее:
1. Запрос уходит на сервер
2. Сервер решает, что это – вопрос о коде, и запускает векторный поиск по embedding'ам, которые заранее были созданы на сервере во время “индексации” проекта
3. По результатам векторного поиска сервер понимает, какие файлы могут быть релевантны и запрашивает эти конкретные файлы обратно у клиента
4. Клиент шлёт нужные части кода (зашифрованно) – только те, что реально понадобились
5. Сервер “собирает” полный контекст и запускает inference для ответа
6. Ответ возвращается в чат
Отдельно стоит рассказать, как Cursor узнаёт, какие файлы изменились, и переиндексирует только их. Для используются Merkle-деревья:
1. каждый файл разбивается на чанки, каждый чанк хешируется
2. хеши объединяются попарно и формируют узлы следующего уровня
3. в результате строится дерево, корневой хеш которого отражает состояние всего проекта – аналогичное дерево строится и на клиенте, и на сервере
Каждые ~3 минуты клиент сравнивает свой корневой хеш с серверным:
– если хеши совпадают – индекс остаётся прежним
– если отличаются – обход дерева точно выявляет изменённые чанки, и переиндексирует только их
Недавно вышла немного рекламная, но легкая и интересная статья от The Pragmatic Engineer о том, как устроен Cursor узнутри.
В начале статьи просто любопытные цифры о Cursor. Дальше автор рассказывает нам о технологическом стеке. Из интересного:
- TypeScript – бизнес-логика, критические штуки на Rust
- Turbopuffer – основное KV-хранилище, держит зашифрованные файлы + Merkle-деревья для синка
- Pinecone – векторная БД для семантического поиска по коду
- Datadog, PagerDuty, Sentry, Amplitude для обзервабилити
- Linear – для таск трекинга (рекомендую попробовать для тех, кто не пробовал, интересное решение)
Cursor не хранит наш код на своих серверах. Когда вы отправляете запрос в Chat, происходит следующее:
1. Запрос уходит на сервер
2. Сервер решает, что это – вопрос о коде, и запускает векторный поиск по embedding'ам, которые заранее были созданы на сервере во время “индексации” проекта
3. По результатам векторного поиска сервер понимает, какие файлы могут быть релевантны и запрашивает эти конкретные файлы обратно у клиента
4. Клиент шлёт нужные части кода (зашифрованно) – только те, что реально понадобились
5. Сервер “собирает” полный контекст и запускает inference для ответа
6. Ответ возвращается в чат
Отдельно стоит рассказать, как Cursor узнаёт, какие файлы изменились, и переиндексирует только их. Для используются Merkle-деревья:
1. каждый файл разбивается на чанки, каждый чанк хешируется
2. хеши объединяются попарно и формируют узлы следующего уровня
3. в результате строится дерево, корневой хеш которого отражает состояние всего проекта – аналогичное дерево строится и на клиенте, и на сервере
Каждые ~3 минуты клиент сравнивает свой корневой хеш с серверным:
– если хеши совпадают – индекс остаётся прежним
– если отличаются – обход дерева точно выявляет изменённые чанки, и переиндексирует только их
Pragmaticengineer
Real-world engineering challenges: building Cursor
Cursor has grown 100x in load in just a year, sees 1M+ QPS for its data layer, and serves billions of code completions, daily. A deepdive into how it’s built with cofounder, Sualeh Asif
👍6
Forwarded from ITKatya: культурные паттерны в IT
🏗 Как DDD помогает на этапе архитектуры и проектирования
1. Делит по смыслу, а не по слоям
DDD предлагает смотреть на систему как на совокупность смысловых контекстов, а не просто «вот тут сервис, вот тут контроллер».
Архитектура строится по бизнес-логике, а не по технологическим паттернам.
→ Вместо «сервис каталога» — «управление товарными категориями».
→ Вместо «бэк-офис» — «расчет комиссий».
📦 Это дает:
— ясные границы владения данными и логикой,
— меньше связей между частями системы,
— выше устойчивость к изменениям.
2. Позволяет не смешивать несовместимое
Если в одном модуле встречаются и бизнес-логика, и интеграции, и админ-панель, и метрики — это все пахнет монолитом боли (но не всегда! И, да, только на длительной дистанции!).
DDD подсказывает: все, что живет по разным правилам — должно жить в разных контекстах.
🧠 Пример: расчет пеней по кредитам и формирование/выдача индивидуальных кредитов — разные контексты. Разный язык, разная частота изменений, разные источники истины.
3. Как мешает (если применять неправильно)
— Переусложнение на старте
Выделять bounded context ради bounded context — вредно.
Если вы на MVP стадии и продукт еще не понял сам себя — не надо ваять архитектуру на 100 лет вперед.
— Слишком формально
DDD — это не UML и не жесткий шаблон.
Если вы пишете спецификацию на каждый value object, но не можете поговорить с бизнесом — это не DDD, это бюрократия.
4. Связь с языком и контекстами
Каждое архитектурное решение должно проходить через язык:
Если внутри одного bounded context у вас есть «user», который одновременно и платит, и нанимает, и модератор — это уже тревожный звонок.
🎯 Проверка: можно ли без ошибок перевести требования бизнеса в термины архитектуры?
5. Как проверять деление на домены и замкнутость контекстов
— Есть ли своя модель данных?
— Есть ли уникальные бизнес-правила?
— Меняются ли эти правила независимо от других частей?
— Понимает ли одна и та же команда, как это работает?
— Можно ли заменить этот контекст без масштабного рефакторинга всей системы?
Если «да» — у вас скорее всего здоровый bounded context.
🤔 Всегда ли нужно?
Нет. Если у вас микропроект на 3 человека — достаточно здравого смысла.
Но если проект растет, появляется несколько команд, увеличивается сложность, разрастается предметная область — без архитектурных принципов DDD вы начнете тонуть в хаосе.
В понедельник поговорим про разработку и реализацию, а пока:
💬 Ваша архитектура отражает бизнес? Или просто похожа на «все как у людей»?
#architecture #ddd
1. Делит по смыслу, а не по слоям
DDD предлагает смотреть на систему как на совокупность смысловых контекстов, а не просто «вот тут сервис, вот тут контроллер».
Архитектура строится по бизнес-логике, а не по технологическим паттернам.
→ Вместо «сервис каталога» — «управление товарными категориями».
→ Вместо «бэк-офис» — «расчет комиссий».
📦 Это дает:
— ясные границы владения данными и логикой,
— меньше связей между частями системы,
— выше устойчивость к изменениям.
2. Позволяет не смешивать несовместимое
Если в одном модуле встречаются и бизнес-логика, и интеграции, и админ-панель, и метрики — это все пахнет монолитом боли (но не всегда! И, да, только на длительной дистанции!).
DDD подсказывает: все, что живет по разным правилам — должно жить в разных контекстах.
🧠 Пример: расчет пеней по кредитам и формирование/выдача индивидуальных кредитов — разные контексты. Разный язык, разная частота изменений, разные источники истины.
3. Как мешает (если применять неправильно)
— Переусложнение на старте
Выделять bounded context ради bounded context — вредно.
Если вы на MVP стадии и продукт еще не понял сам себя — не надо ваять архитектуру на 100 лет вперед.
— Слишком формально
DDD — это не UML и не жесткий шаблон.
Если вы пишете спецификацию на каждый value object, но не можете поговорить с бизнесом — это не DDD, это бюрократия.
4. Связь с языком и контекстами
Каждое архитектурное решение должно проходить через язык:
— Как называется эта часть?
— Какие слова в ней допустимы?
— В каком контексте они значат то, что значат?
Если внутри одного bounded context у вас есть «user», который одновременно и платит, и нанимает, и модератор — это уже тревожный звонок.
🎯 Проверка: можно ли без ошибок перевести требования бизнеса в термины архитектуры?
5. Как проверять деление на домены и замкнутость контекстов
— Есть ли своя модель данных?
— Есть ли уникальные бизнес-правила?
— Меняются ли эти правила независимо от других частей?
— Понимает ли одна и та же команда, как это работает?
— Можно ли заменить этот контекст без масштабного рефакторинга всей системы?
Если «да» — у вас скорее всего здоровый bounded context.
🤔 Всегда ли нужно?
Нет. Если у вас микропроект на 3 человека — достаточно здравого смысла.
Но если проект растет, появляется несколько команд, увеличивается сложность, разрастается предметная область — без архитектурных принципов DDD вы начнете тонуть в хаосе.
Практические примеры (финтех):
Интернет-банк разбивается на контексты: «Accounts» (Счета), «Payments» (Платежи), «Loans» (Кредиты), «Cards» (Карты), «Analytics/Reporting» (Отчеты). Каждый из них соответствует своей части бизнеса и управляется отдельной командой. Например, команда контекста Payments владеет всем, что связано с переводами: у них свой словарь (платеж, транзакция, комиссионные и т.д.) и своя кодовая база. В другом контексте Accounts – свой словарь (баланс, счет, клиент и т.п.). Эти команды работают параллельно, а взаимодействуют их сервисы через четко определенные API. При этом термин «Transaction» в контексте платежей имеет одно значение (конкретное движение денег), а в контексте аналитики, скажем, это может быть абстрактный объект для агрегированной статистики. Благодаря DDD эти понятия разведены: без выделения контекстов компания получила бы единую громоздкую систему, где разные отделы говорили бы «транзакция» о разном и путали друг друга.
В этом примере команда Accounts и команда Payments могут работать автономно, выпуская изменения независимо – изменение в сервисе счетов не сломает сервис платежей, если контракт (например, API запроса баланса) остался прежним.
В понедельник поговорим про разработку и реализацию, а пока:
💬 Ваша архитектура отражает бизнес? Или просто похожа на «все как у людей»?
#architecture #ddd
👍3
Forwarded from Evgeniy Pyatkov
Подскажи, я попробовал copilot, он мне сильно помог с написанием прослойки для фронта. Но вот думаю теперь, что попробовать еще, в copilot вроде уже завезли gpt-5, стоит ли оставаться на нем. Или лучше перейти на cursor?
Шикарный вопрос! Смотри, есть ещё одна очень важная деталь, которую нужно понимать при выборе агента: агенты отличаются не только по фичам.
То есть, сейчас очевидно, что Cursor — явный лидер по фичам: его автодополнение с помощью табов единственное, которое корректно работает на всём рынке, в нём доступны все модели, которыми ты когда-либо захочешь воспользоваться, у него есть скидки на использование моделей т.е. платишь $60, получаешь лимиты на $70, также есть фоновые агенты, Max Mode с расширенным контекстом, огромное коммьюнити, автоматическая генерация рулзов. В общем, все остальные агенты по фичам сейчас находятся в роли догоняющих. Ситуация настолько патовая, что бэкендеры генерируют ответы в Cursor, а пишут код в Rider IDE... Стоп, что? Зачем бэкендеры так делают, если у них доступен Windsurf в виде плагина?... Давай разбираться)
Прежде всего есть разные варианты того, как можно собрать контекст по проекту. Сейчас, правда, все поголовно используют RAG, так как его проще всего реализовать, но помяни мои слова первый агент, который научится строить Knowledge Graphs на основе кодовой базы вырвется вперёд в этой гонке. Проблема RAG как раз в том, что он не умеет работать с большими кусками данных, не умеет связывать сущности то есть RAG слабо понимает как TooltipContainer и TooltipIcon связаны между собой, но уже сейчас, не особо понимая, как части проекта связаны между собой он выдаёт достаточно хорошие ответы, чтобы мы могли сильно ускориться, представь что случится, когда агенты будут чётко понимать как разные части кода связаны между собой:)
Это было небольшое лирическое отступление, но оно позволяет хорошо понять, что изнутри агенты могут быть сильно по-разному устроены. Конкретно то, что уже сейчас используют разработчики агентов и основная их фишка — fine tunning. Каждый агент пишет разные промпты, чтобы модель могла выполнить твою задачу. И добавление новой модели требует глубокого понимания того, как она устроена. Сейчас GPT-5 в самом худшем состоянии, в котором мы её когда-либо увидим в агентах, но не потому что OpenAI её доработает (хотя, и такое возможно, конечно), а потому что её нужно зафаинтюнить, чтобы она корректно работала. Почему это не понадобилось делать при переходе с Claude 3.7 на Claude 4? Просто потому что это та же самая модель, но на условные 20% лучше, в то время как GPT-5 — модель нового поколения и к ней тот фаинтюнинг, что был применим ко всем прошлым моделям GPT просто не применим, поэтому пока разработчики агентов не поймут как отфаинтюнить GPT-5 мы будем наблюдать различные артефакты. Почему я предлагаю переходить на Cursor и почему бэкендеры используют Cursor, когда есть возможность пересесть на Windsurf? Ребята из Cursor лучше всего фаинтюнят модели и прямо сейчас теснее всех работают с OpenAI, для того чтобы затащить лучший экспириенс для GPT-5, какой они могут. Тут ещё важно сказать, что мы не получили идеальную ✨интеграцию GPT-5 в Cursor со старта, потому что сами OpenAI не понимают как их модель работает (в целом, это относится ко всем компаниям и моделям, просто правда такова, что мы не понимаем как работает ИИ под капотом и чем дальше, тем больше будем не понимать).
Так что ответ на твой изначальный вопрос — однозначно переходи на Cursor)
Ты получается не подписку юзаешь, а чисто по токенам?
До появления GPT-5 сидел на подписке, но сейчас планирую перейти на токены, так как в этом действительно появился смысл. Ту статистику по расходам, которую я приводил я просто брал из админки Cursor, она была нужна мне для своего исследования фактической стоимости моделей)
Похоже пора заводить свой канал про ИИ 😅
👍5😁2❤1🔥1