Everything I asked while rewriting the ingest service

Back to list2026-08-05
You

I deleted 12M rows and the index is still the same size. Why?

ChatGPT

Deleting rows marks them dead but leaves index entries until vacuum reclaims the pages, and even then the pages stay allocated to that index. REINDEX INDEX CONCURRENTLY is what actually returns the space.

You

How many database connections should a service with 4 workers open?

ChatGPT

Start from cores, not workers. A pool of about twice the database core count is the usual ceiling, so 8 to 16 for a small instance. Beyond that throughput flattens and latency grows, because the connections queue inside postgres instead of in your pool.

You

Should I store user settings as JSONB or as real columns?

ChatGPT

Columns for anything you filter or join on, JSONB for the long tail nobody queries. The moment you write a WHERE settings->>'plan' = ... that runs often, that key has earned a column and an index.

You

timestamptz or timestamp for event times?

ChatGPT

timestamptz almost always. It stores a point in time in UTC and converts on the way out; timestamp stores a wall clock reading with no idea which wall it was on, which becomes unrecoverable once daylight saving moves.

You

Adding a NOT NULL column locked our table for two minutes. How do people avoid that?

ChatGPT

Split it: add the column nullable, backfill in batches, add a validated check constraint, then set NOT NULL. Each step takes a brief lock instead of one long one, and the backfill can be paused if replication lag grows.

You

Is there a fast approximate count for a huge table?

ChatGPT

For monitoring, read reltuples from pg_class, which the planner keeps roughly current. It is off by a few percent between vacuums, which is fine for a dashboard and wrong for invoicing.

You

The index exists but EXPLAIN shows a sequential scan.

ChatGPT

Usually one of three things: the query returns a large fraction of the table so the scan really is cheaper, the types do not match so the index is not applicable, or statistics are stale. ANALYZE the table first, then compare with SET enable_seqscan = off to see what the planner thinks the index would cost.

You

Users see their own edits disappear after saving. Replica lag?

ChatGPT

Almost certainly. Route reads that follow a write by the same user to the primary for a short window, or track the write LSN in the session and wait for the replica to reach it. The general fix is read-your-writes consistency, not lower lag.

You

A comprehension building 2M items is slower than the equivalent loop. Expected?

ChatGPT

Not usually, so look at what is inside. A comprehension that calls a method per item pays the attribute lookup every time; hoisting it out (append = out.append) or using a generator when you do not need the list is what actually moves the number.

You

A 300 MB JSON array does not fit comfortably in memory. Options?

ChatGPT

Stream it. Either a pull parser like ijson, or, if the structure is a flat array of objects, read in chunks and use json.JSONDecoder().raw_decode to peel one object at a time. Memory then depends on the largest single object, not on the file.

You

Is there a real reason to use dataclasses over dicts for internal data?

ChatGPT

Typos become errors instead of silent None, and the field list is documentation that cannot drift. The cost is a small allocation overhead, which matters only in the hottest loops. With slots=True even that mostly disappears.

You

Should the venv see system site-packages?

ChatGPT

No, except when you deliberately depend on a system build of something heavy like GTK bindings. Inheriting site-packages is the most common source of "works on my machine", because the environment is no longer described by requirements alone.

You

How specific should except clauses be?

ChatGPT

Specific enough that an unexpected failure still crashes. except Exception around an entire request handler is fine if it logs and re-raises in development; the same clause around three lines of parsing will swallow the typo that broke them.

You

Where do you start adding type hints to an existing project?

ChatGPT

At the boundaries: function signatures on public modules first, internals never. Run the checker in non-blocking mode for a few weeks so the noise is visible without stopping anyone, then turn on strictness one module at a time.

You

Is shell=True ever acceptable?

ChatGPT

When the command genuinely is a shell pipeline you control end to end, and never with any value that came from outside the program. The list form avoids quoting entirely, which is both safer and easier to read.

You

How do I structure a file that is both a module and a CLI?

ChatGPT

Keep the work in functions, put argument parsing in main(), and guard with if __name__ == "__main__": sys.exit(main()). Return codes from main then work for both the shell and the tests.

You

Small service, limited time. Which one first?

ChatGPT

Logs with structure, because they answer "what happened" for incidents you did not anticipate. Metrics come next for the handful of numbers you would page on. Traces are worth it once a request crosses more than two services.

You

Our alerts fire constantly and everyone mutes them.

ChatGPT

Alert on symptoms users feel, not on causes. Disk at 85% is a cause and often harmless; requests failing is a symptom and always matters. Every alert that cannot be acted on immediately should be a dashboard instead.

You

Our metrics cost exploded after adding a user id label.

ChatGPT

That is the mechanism: every distinct label value creates a series. User ids, request ids and full URLs never belong in labels. Put them in logs and traces, where high cardinality is the point rather than the problem.

You

Head sampling drops exactly the requests I want to see.

ChatGPT

Tail sampling: buffer the spans and decide after the outcome is known, keeping everything that errored or exceeded a latency threshold plus a small random slice of the rest. Costs more memory at the collector and is almost always worth it.

You

Everything passes locally and CI fails at random.

ChatGPT

Three usual causes: leftover state between tests that a fresh CI container does not have, timing assumptions that a slower machine breaks, and a shared resource like a fixed port or a real clock. Run the suite locally in a random order to reproduce the first one.

You

Is 80% coverage a reasonable target?

ChatGPT

Coverage measures what ran, not what was checked. A suite at 80% with meaningful assertions is healthy; the same number reached by importing modules is decoration. Track it as a trend and never as a gate.

You

Mock the HTTP client or spin up a fake server?

ChatGPT

A fake server, when the protocol matters. Mocks encode your belief about the API, so they keep passing after the real one changes. A local server exercises serialisation, headers and timeouts, which is where the bugs actually live.

You

Which edge cases deserve a test in a small project?

ChatGPT

The ones that already bit you, and the boundaries: empty, one, many, malformed, and the largest input you claim to support. That list catches most regressions without turning the suite into a second implementation.