Skip to content
laluka

Demo workspace Tidewatch is a made-up tide API. The lessons are real laluka lessons about it. Your own repos arrive with sign-in.

Tides route caps days at 14 and says so

Origin: authoredStatus: confirmedRepo: tidewatch-apiCard: TW-212Branch: tw-212-days-limitWritten: 19 Sept 2026Size: 9 files, +171 -22 (large: lines, files)

What

The tides route now refuses days above 14 with a 400 that states the range. Before, any number was accepted and a request for a year of tides was computed in full.
Cites

Why

Card TW-212: one client asked for 365 days per station every night and each call held a worker for about 40 seconds. The cap is the smallest change that stops that without touching the prediction code.
Cites

How

parseTideQuery validates days as a whole number from 1 to MAX_DAYS before anything is computed, and returns the message with the limit in it so the client can fix itself.

What breaks

Any client asking for more than 14 days now gets 400 instead of data. They have to page by date. Responses for 1 to 14 days are unchanged.

Alternatives

Streaming long ranges was considered and left for later: it keeps the worker busy just as long. A per-plan limit was rejected for now because only one client is affected.
Cites
Believed before
days is unbounded, ask for as many as you like.
True now
days is 1 to 14. Page by date for longer ranges.

Cites

  1. [1]src/routes.ts:4-13matchSupports: what
    [lines 4-13 of a 16-line file]
    const MAX_DAYS = 14;
    // GET /v1/stations/:id/tides?from=YYYY-MM-DD&days=N
    export function parseTideQuery(id: string, from: string, days: string | undefined) {
    const station = getStation(id);
    if (!station) return { status: 404 as const, error: `Unknown station: ${id}` };
    const n = days === undefined ? 1 : Number(days);
    if (!Number.isInteger(n) || n < 1 || n > MAX_DAYS) {
    return { status: 400 as const, error: `days must be a whole number from 1 to ${MAX_DAYS}` };
    }
  2. [2]src/routes.ts:10-12matchSupports: why
    [lines 10-12 of a 16-line file]
    const n = days === undefined ? 1 : Number(days);
    if (!Number.isInteger(n) || n < 1 || n > MAX_DAYS) {
    return { status: 400 as const, error: `days must be a whole number from 1 to ${MAX_DAYS}` };
  3. [3]src/rate-limit.ts:1-3matchSupports: alternatives
    [lines 1-3 of a 8-line file]
    // Fixed window, per API key. The window is one minute and the limit is per plan.
    export const LIMITS = { free: 30, harbour: 300 } as const;
    export type Plan = keyof typeof LIMITS;

Card

What is the most days of tides one request can ask for, and what happens above it?
junior
Show the answer
14. Above that the route returns 400 naming the 1 to 14 range, and nothing is computed.
Cites[1]

Questions

junior

Where is the days limit enforced?
junior
Show the answer
In parseTideQuery in src/routes.ts, before any prediction is computed.
Cites[1]

mid

Why a hard cap rather than streaming the long range?
mid
Show the answer
Streaming keeps the worker busy for just as long. The problem was worker time, so the cap fixes it and streaming does not.
Cites[2]