Двенадцатого сентября у меня не было ни домена, ни строчки кода. Шестнадцатого есть сайт из сорока шести страниц, который отвечает на вопрос «доеду ли я до такого-то города на том, что сейчас в баке, и где последняя заправка, до которой хватит».
Сразу оговорюсь, чтобы дальше не было недоразумений: это не история успеха. Проекту пять дней, трафика ноль, поисковики его только начали смотреть. Я не знаю, полетит он или нет, и статья не об этом.
Она о другом — о том, из чего состоит первая неделя. Как выбирается ниша, если не полагаться на чутьё. Почему готовое решение пришлось выбросить и считать самому. И сколько за эти пять дней нашлось мест, где я был совершенно уверен и совершенно неправ.
Коротко
- Нишу выбирал не наитием, а замером: 351 пара городов, у каждой измерен спрос.
- Готовый маршрутизатор занижает скорость на 20–30%, то есть завышает время примерно на треть. Пришлось строить свою модель по телеметрии.
- Одна цифра прожила в четырёх моих отчётах подряд и перевернула вывод на противоположный — потому что сверить её было неудобно.
- Главный вывод: опаснее всего ошибки, которые выглядят как успех.
Откуда взялась идея
Я держу сервис GPS-мониторинга, и там есть весь нужный инструментарий: свой маршрутизатор на данных OpenStreetMap, выгрузки карт, опыт работы с координатами. Возник вопрос: что ещё можно построить на том, что уже есть?
Обычный ответ — придумать продукт и проверить спрос. Я сделал наоборот: сначала измерил спрос, потом выбрал, что строить.
Причина в предыдущем опыте, довольно болезненном. На основном сервисе я завёл тысячу страниц — по одной на каждую модель трекера — и был уверен, что это золотая жила. Реальные заходы оказались у считанных единиц. Я тогда выбирал по догадке «это ведь ищут», и догадка стоила недели работы.
Поэтому здесь я начал с замера. Запрос «расстояние от города до города» — один из самых частых в русскоязычном поиске, и на него отвечают десятки калькуляторов. Все они говорят одно и то же: километры, часы, иногда расход топлива в литрах. Никто не отвечает на вопрос, где бензин кончится и какая заправка последняя, до которой хватит.
Вот эта щель и стала проектом.
Как я выбирал пары городов
Пул — 351 пара, после отсева спутников крупных городов и слишком коротких маршрутов. У каждой измерен спрос. Медиана — 1140 показов в месяц, хвост списка — 87, то есть уже на уровне шума самого замера.
Первая волна — сорок пять пар с наибольшим спросом, от 15 414 до 4 057 показов.
И вот тут случилось то, ради чего я, собственно, и пишу эту статью.
Число, которое прожило четыре отчёта
Замер спроса упирается в ограничение сервиса: сто запросов в час. Поэтому он шёл фоном, партиями, несколько часов. Я время от времени докладывал состояние: «замерено 254 пары из 353».
Эта цифра держалась в четырёх моих отчётах подряд. Она была неверной.
Файл с результатами накапливался дольше, чем жил список пар. В какой-то момент список пересобрали — а файл остался прежним, и в нём смешались замеры по двум разным версиям. Из 254 строк текущему списку принадлежали сто. Остальные сто пятьдесят три были от прежнего.
Заметьте: ни ошибки, ни сбоя. Строки выглядели одинаково — в них нет пометки, из какого списка пара. Считать «сколько готово» длиной файла было удобно, и это удобство стоило четырёх отчётов.
Но дело не в цифре. Дело в том, что вывод оказался обратным.
На смешанном наборе в верхушке спроса не было ни одной пары с Москвой. Отсюда родилось наблюдение, которое я успел всем рассказать: спрос сидит в региональных парах среднего плеча, а московские направления переоценены.
На правильно сопоставленном наборе первые шесть мест — все шесть — занимают пары с Москвой.
У меня есть объяснение задним числом, и оно правдоподобное: Москва — самый населённый город, и запросов с ней много почти в любом направлении. Но правдоподобное объяснение задним числом — это не измерение, и я держу его как догадку, а не как вывод.
Приятная деталь: Москва—Казань, единственная опубликованная к тому моменту страница, оказалась парой номер один по спросу во всём списке. Выбрал я её раньше и совсем по другим причинам. Повезло, а не подогнал.
Почему я не взял время у готового маршрутизатора
Первая версия страницы показывала время, посчитанное маршрутизатором OSRM. Это стандартный инструмент, им пользуются все.
Я сверил его предсказания со своими реальными поездками — у меня есть телеметрия за год, тысячи точек с координатами и скоростью. На четырёх проверочных днях маршрутизатор давал 66–70 км/ч там, где по факту выходило 79–86.
Он занижает скорость на 20–30%. Это значит, что время он завышает примерно на треть: восьмичасовая дорога превращается в одиннадцатичасовую.
Причина не в ошибке разработчиков. Маршрутизатор считает по скорости, назначенной классу дороги, а не по реальному ограничению на конкретном участке. На новой скоростной трассе с лимитом 130 разрыв особенно заметен.
Здесь была развилка. Можно было показывать чужую цифру и не отвечать за неё — так делают все, и никто не в претензии. Я решил считать сам.
Что получилось
Три скорости, измеренные по собственным трекам:
125,5 км/ч скоростная трасса
87,9 км/ч обычная трасса вне застройки
46,8 км/ч застройка
Проверка — восемь других дней, коэффициенты не пересчитывались. Средняя ошибка 4,4% против 20–30% у маршрутизатора.
Отдельно про один день, где ошибка вышла 15,3%. Разбор показал две причины: в тот день мой реальный путь физически разошёлся с расчётным маршрутом на 16%, и 210 километров трека вообще не нашли дороги в выгрузке карт — я заказал слишком узкую рамку. Это не изъян метода, а честная граница данных. Проверочная выборка ровно для того и нужна, чтобы такое всплывало.
Где я не знаю и говорю об этом
Телеметрия у меня есть по тем дорогам, по которым я ездил. По остальным скоростным трассам своего замера нет, и там модель считает их как обычные — то есть время выходит завышенным.
На таких страницах написано «не больше N часов», а не «около N часов». Это разные утверждения, и разделение сделано в коде явно, а не оставлено на усмотрение того, кто пишет текст.
Мне это кажется важнее точности. Точность можно нарастить; привычку не выдавать незнание за знание — нет.
И ошибка в моей же формулировке
Пока писал страницу с описанием методики, поймал себя: я говорил «маршрутизатор ошибается на 20–30%». Но занижение скорости на четверть и завышение времени на четверть — это разные числа. Правильно: скорость занижается на 20–30%, время завышается примерно на треть.
Фраза звучала одинаково убедительно в обоих вариантах. Разница нашлась только тогда, когда понадобилось объяснить читателю, откуда цифра.
Карта, которая работала слишком хорошо
Изначально маршрут на странице был абстрактной линией — просто ломаная на белом фоне. Посмотрел на это и решил, что нужна настоящая карта: без неё человек не понимает, где именно он едет и что вокруг.
Сделал: подложка из данных OpenStreetMap, отрисованная своим кодом, маршрут поверх неё, цвет линии меняется по остатку топлива.
Замерил в браузере — и схватился за голову. 20 295 элементов в разметке, 1,6 мегабайта. Страница грузилась почти две секунды на телефоне, а перекраска после ввода своих цифр занимала 813 миллисекунд. До карты она была мгновенной.
Причина оказалась не в объёме как таковом. Подложка статична — она не меняется никогда, ни от чего. Но жила она в том же месте, что и линия маршрута, которая перерисовывается на каждое нажатие клавиши. Браузер честно пересчитывал всё.
Решение: отрисовать подложку один раз при сборке сайта и сохранить картинкой. Своим кодом, из своих данных — не запросом к чужому серверу карт. В живой разметке осталось только живое: линия и подписи.
Стало 510 элементов вместо 20 295. Отклик на телефоне — 410 мс вместо 813, на дешёвом аппарате 541 мс.
И цена, которую я узнал только вчера: растеризация занимает 20 секунд из 25 на страницу. Когда понадобилось обновлять цены на топливо еженедельно, это оказалось узким местом — полная пересборка занимала девятнадцать минут, из которых собственно расчёт занимал секунды. Теперь подложка переиспользуется, и вся волна собирается за 5,3 секунды.
Три цены за одну дорогу
Лучший эпизод всей истории, и он не про код.
На странице Москва—Казань есть платная трасса, и надо было указать её стоимость. Первая версия: «от 5000 ₽» — круглое число, найденное в поиске.
Потом я нашёл «точнее»: «от 4998 ₽, тариф зависит от времени суток». Некруглое число плюс объяснение — выглядит куда солиднее.
Потом я взял сами приказы оператора. По приказу от 27 февраля 2026 года проезд стоит 5847 ₽, и от времени суток не зависит вовсе.
Неверными оказались оба прежних утверждения — и цена, и оговорка про время суток. Причём вторая версия была убедительнее первой, будучи дальше от правды. Некруглые числа внушают доверие именно потому, что выглядят результатом измерения.
Главное в приказах — не в таблицах
Разбирая приказы, я обнаружил, что числа в них — самая простая часть. Смысл живёт в сносках.
Пример. На одной трассе два пункта оплаты стоят на одном и том же платном участке — и сноска говорит, что при проезде насквозь платишь один раз, а не на каждом. Алгоритм «какие пункты прошли, те и суммируем» посчитал бы вдвое. Таких пар в одном приказе нашлось три.
Другой пример, на этот раз про мою собственную ошибку. У одного участка я записал оператором организацию с аббревиатурой, найденной в документе. По сноске выяснилось, что эта организация — эмитент транспондеров, то есть способ оплаты. Я записал платёжную систему в графу «кто владеет дорогой».
Правило, которое я теперь применяю ко всем официальным документам: читать с конца. Сначала сноски и примечания, потом таблицы. Цифра без своей оговорки — это не половина факта, а другой факт.
И случай, где документ не помог
На одной трассе два платных участка накладываются друг на друга, и из текста приказа не следует, платит ли проезжающий насквозь за оба. Разница между 530 и 310 рублями — не округление, а разные утверждения о деньгах.
Страница по этой дороге молчала о цене, пока я не знал ответа. Разрешилось не документом, а поездкой: я по ней езжу и знаю, что списание происходит на каждой рамке. В моих записях у этой цифры помечено, что источник — опыт, а не документ.
Маршрут, который шёл через другую страну
Этот случай мне до сих пор неуютно вспоминать.
Екатеринбург—Омск. Кратчайший путь идёт через Казахстан: 188 километров по чужой территории, два пересечения границы. На странице не было ни слова «Казахстан», ни слова «граница». Тридцать две заправки из ста девяноста одной были казахстанскими — и предлагались как обычные точки на дороге, вместе с советом, до какой из них хватит бака.
Нашлось случайно. Я привязывал маршруты к регионам, чтобы подставлять местные цены на бензин, и у одного маршрута 188 километров не находили никакого субъекта федерации. Решил, что дыра в данных о границах. Дыры не было — была граница государственная.
А самое неприятное вот что: в описании дороги на той же странице прямым текстом стоял казахстанский код трассы. Данные говорили правду с самого начала. Читать было некому.
Страница, которая обещала то, чего не показывает
Мелкий случай, но точно про то же самое.
Я сделал фильтр по сетям заправок и написал в подсказке: «остальные заправки показаны на схеме бледными». Код был написан верно, фильтр работал.
Проверил в браузере: значков на схеме два, из них бледных — ноль. Мелкие значки почти никогда не помещаются, их отсекает защита от наложения подписей. Гасить было нечего.
Обещание, которого страница не держит, хуже отсутствующего. Отсутствие ничего не обещает и потому не лжёт.
Что есть и чего нет
Пишу честно, без округлений в свою пользу.
Есть: 46 страниц маршрутов, суммарно почти 25 тысяч километров. Стоимость платных участков на четырнадцати из них — посчитанная по приказам, с номером и датой. Интерактивная карта, где можно поставить свои точки. Цены на топливо по регионам из недельной сводки Росстата, обновляются сами. Страница с описанием методики.
Нет: пробок — время не зависит от часа выезда. Погоды и сезона — зимняя трасса считается как летняя. Цены на конкретной колонке — только средняя по региону. Своего замера скорости на большинстве скоростных трасс — там честное «не больше N часов». И трафика: пять дней, поисковики только начали смотреть.
Главный урок
Я веду файл с разбором собственных ошибок по этому проекту. За пять дней в нём двадцать три случая. Перечитал их сегодня и понял, что все они про одно.
Опаснее всего ошибки, которые выглядят как успех.
Ни одна из перечисленных не давала сбоя. Сервис отвечал. Страница открывалась. Число приходило. Проверка была зелёной.
Служба, отдающая ответ с кодом «успешно», в котором спрятано сообщение об ошибке. Обработчик, превративший отказ в «данных нет». Цифра, прожившая четыре отчёта, потому что сверить её было неудобно. Настройка, которую никто не читает. Проверка сервиса одним запросом — при двенадцати одновременных он падал десять раз из двенадцати.
Каждый раз результат был получен, выглядел правдоподобно и вёл не туда.
Отсюда правило, которым я теперь пользуюсь везде: у всякой проверки надо отдельно спросить, а могла ли она сказать «нет». И отвечать на это не рассуждением, а прогоном — сломать нарочно то, что она обязана поймать. Если сломать нечем или непонятно чем, она не проверяет, а подтверждает.
Есть и второе, которое я вывел на этой неделе. Часть работы шла у меня с ИИ-агентами — держу по одному на проект, и они перепроверяют друг друга. Так вот: второй проверяющий помогает ровно настолько, насколько смотрит другим способом. Двое, считающие одним методом, — это не две проверки, а одна, сделанная дважды. Половина находок в этой статье появилась не потому, что кто-то был внимательнее, а потому что смотрел не туда, куда смотрел первый.
Что дальше
Ждать. Домен пятидневный, поисковики только начали читать карту сайта.
Дальше по плану — вторая волна страниц, но не раньше, чем станет видно, что произошло с первой. Сорок пять страниц одним днём на домене без истории — это силуэт, за который наказывают, и я предпочту узнать это на сорока пяти, а не на трёхстах.
А пока проект стоит ровно там, где его интереснее всего разглядывать: всё построено, ничего не доказано.
Посмотреть, что получилось: dotyanu.ru. Там же страница «Как мы считаем — и чего не знаем»: откуда берутся скорости, заправки и цены платных участков, и что именно сервис не умеет.
Продолжение будет в середине октября, примерно через месяц. К этому времени станет видно то, чего сейчас нет: взяли ли поисковики страницы в индекс, по каким запросам они показываются и приходит ли кто-нибудь. Тогда же будет ответ на главный вопрос — работает ли ставка на то, что мы считаем сами, а не пересказываем чужие цифры.
Если окажется, что не работает, я напишу и об этом. Разбор неудачи полезнее ещё одной истории успеха.