#バックエンド
15 件
ファイルの原子的書き込み:一時ファイルに書いてから rename
上書きは停電・クラッシュ・並行読み取りの瞬間に半端なファイルを残します。一時ファイルと rename を使えば、ファイルシステムの原子性で「半端」を不可能にできます。
工数見積もり:なぜ「だいたい三日」が三週間になるのか
見積もったのはコーディング時間で、約束したのは実装+結合+レビュー+手戻り+待ち時間です。不確かな部分を明示する方が、日数を二倍するより効きます。
フィーチャーフラグ:設定ではなく負債である
フラグは到達可能なコード経路を倍にし、そして自動では消えません。精巧な仕組みを作るより、各フラグに削除日を決める方がはるかに重要です。
グレースフルシャットダウン:終了手順が 502 と正常応答を分ける
終了信号で即座に exit すると処理中の要求が切られます。正しい順序は、新規受付の停止、処理中の完了待ち、資源の解放、そして終了です。
冪等キー:再試行を安全にする一回の書き込み
ネットワークのタイムアウトはサーバが何もしなかった証拠ではありません。冪等キーで同一リクエストを識別し、再実行せず最初の結果を返します。
JSON 正規化:同じオブジェクトが二つのハッシュになる理由
キーの順序、数値の表記、エスケープの仕方でバイト列は変わります。ハッシュを安定させるには、JSON.stringify に期待せずシリアライズ層で規則を固定します。
デッドロック:四つの条件のどれか一つを壊せばよい
相互排他・保持と待機・横取り不可・循環待機。四つが同時に成立して初めて起きます。実務で壊しやすいのは循環待機で、ロックに全体順序を与えます。
N+1 クエリ:ORM で最も典型的な性能の罠
100 件を取り出してから一件ずつ関連を引くと 101 回のクエリになります。直し方は三つだけです。先読み、一括取得、あるいは一回の JOIN。
レート制限:トークンバケットと漏れバケットの実際の違い
トークンバケットは突発を許し、漏れバケットは一定速度に均します。選び間違えると、正常な利用者が制限されたり、制限が機能しなかったりします。
SQLite のインデックス:最左前置は制約ではなく整列の帰結
複合インデックス (a, b) は a が等しい範囲でのみ b が整列します。a を飛ばして b で絞るのは、使えるものが無いというだけのことです。整列として捉えれば暗記は不要です。
タイムゾーンと夏時間:UTC で保存しないと必ず壊れる
夏時間の日は 23 時間か 25 時間で、切り替え付近のローカル時刻は存在しないか二度現れます。UTC で保存し表示時に変換するのが唯一安定する模型です。
Unicode 正規化:見た目が同じ二つの文字列が等しくない理由
é は一つのコードポイントにも、基底文字と結合記号にもなります。比較・保存・索引の前に NFC へ揃えないと、重複やログイン失敗が静かに発生します。
Rust の Result:コンテキストは失敗した行に付ける
`?` はエラーをそのまま上へ投げ、どの段階で失敗したかを伝えません。中核は照合できる構造化エラー、アプリ層は Context で「何をしていたか」と入力を添える。
crate を workspace に分けるべきとき
分割の引き金はビルド時間と依存の境界で、ディレクトリの見た目ではありません。3 つの条件が揃ったときに分け、揃わなければ 1 回のビルドを複数パッケージの管理と引き換えにするだけです。
構造化ログは println を tracing::info に置き換えることではない
文字列を連結したログは人間しか読めません。フィールドがあって初めて検索と集計ができます。フィールド、span、レベル、そして整形しない判断の 4 つが本題です。
