Skip to content

CoderWorkspacePoolMember: recognize a template-wide last_used_at write in a one-member pool #349

Open

Description

@ThomasK33

Problem

A CoderWorkspacePoolMember treats a later last_used_at as use, except for a template-wide write. It recognizes a template-wide write in two ways: the value is within 5 s of the template's updated_at, or another unclaimed member of the pool already moved its baseline to the same value.

When a template schedule update with update_workspace_last_used_at runs, and the template changes again before the next 60 s poll, and no other member of the pool saw the first write (for example a one-member pool), the member marks itself Used. The pool releases it, and one warm workspace leaks.

This is the fail-safe direction: the controller never deletes a workspace that someone may use. But it costs one workspace per affected member.

Possible fix

Also accept as a witness any other workspace of the template in Coder with the same last_used_at (one list call, only when the template time does not match).

Trigger

Before the PR 12 activation docs of #153, or a user report.

Found by Codex on #343 (comment 4268119093).

Refs #153

Found in review of #343 (thread 4268119093); the plan resolves the ambiguity toward Used, which can leak one warm workspace but never deletes possible work.

Refs #153


Generated with xum • Model: anthropic:claude-opus-5-5 • Thinking: medium

Activity

  1. ThomasK33 commented on Oct 14, 2026

    @ThomasK33
    MemberAuthor

    Two more cases from the final assessment of #343, where real use can be counted as "not used" (the side that leads toward replacement, not toward keep). Both windows are short: continued use bumps last_used_at again at the next usage flush, about 60 s later, so only a single short use can be missed.

    1. 5 s template guard false negative. The template's updated_at moves on every template edit (for example a version promote), not only on a schedule update with update_workspace_last_used_at. A use flush within ±5 s of an unrelated template edit is treated as a template-wide write and not counted as use.
    2. Shared-flush sibling collision. Coder's usage tracker writes one shared now to every workspace in a flush batch (coderd/workspacestats/tracker.go, flush). The member compares whole seconds, so a sibling whose baseline came from the same flush or the same second makes this member's real use look like a template-wide write.

    Also for the docs at activation: last_used_at is best-effort. Port-forward or raw tunnel connections with no session do not bump it under the usage experiment, and a failed flush drops updates.

    Gate: decide and document before PR 12 registers the reconciler.


    Generated with xum • Model: anthropic:claude-opus-5-5 • Thinking: medium

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions