Articles
37signals Programmer Take-Home: Scope a Small Project and Explain the Trade-Offs
Prepare for a 37signals programmer take-home by scoping a small complete project, testing its core path, and explaining deliberate trade-offs.
37signals has publicly described using small programmer work samples late in some hiring processes. In a 2025 REWORK podcast, David Heinemeier Hansson said the programmer take-home in the hiring round discussed was designed for about four to six hours. A 2023 37signals internship account also described a small technical assignment followed by a conversation about it. These are dated official accounts, not a promise that every current programmer role has the same prompt, time allowance, or sequence. If you receive an assignment, the instructions in that invitation govern your work.
The best preparation is to practice shipping a small, coherent piece of software and explaining what you deliberately left out.
What the dated official evidence supports
Official, dated: in the August 2025 REWORK episode “Titles, tenure, and paths don't matter,” the 37signals founders discuss looking at actual work rather than treating credentials as decisive. Hansson describes a programmer take-home that could be done in roughly four to six hours in the particular recent round discussed. The episode says the company also looked at writing and earlier work when deciding whom to invite to the test. It does not publish the test prompt or establish a permanent hiring policy for every opening.
Official, dated: a 2023 37signals web programming intern wrote that their process included a phone screen, small technical assignment, and a technical interview about experience and the assignment. That first-person employee account is useful corroboration of a past internship process, but it is not an independent current candidate report or proof of today's senior-role stages. A separate 2023 REWORK conversation described the company valuing self-directed work and using a small programmer sample in that period.
Inference for preparation: a reviewer who uses a short work sample can learn more from one finished path, clear constraints, and honest trade-offs than from a large but half-built framework. This article turns that inference into an original rehearsal project. It does not claim that 37signals assigns the sample below or that a particular framework, language, or architecture wins its review.
Before you code a real assignment, read it twice. Extract the requested behavior, inputs, outputs, deadline and time zone, permitted dependencies, submission format, testing expectations, use-of-AI rules if any, and whether questions may be asked. If anything material is ambiguous, make a reasonable assumption in the README or ask the designated contact. Do not exceed the written timebox because you believe “extra effort” is secretly required.
Rehearsal project: a tiny request-status board
Use this original editorial exercise, not a reported 37signals task: build a small page or command-line app for a support team to track requests. A user can create a request with a short title and description, mark it open or resolved with an optional note, and filter the list by status. Data can be stored in a simple local database or durable file. The goal is one complete path: create, see, update, and filter. There is no login, notification system, analytics dashboard, or deployment requirement in this rehearsal.
Set a four-to-six-hour ceiling only if that matches the real instruction or you are simulating the 2025 account. Allocate time in a way that leaves a working submission. For example, reserve the first part for reading and shaping the smallest path, the main block for implementation, a later block for tests and manual review, and the last block for the README and submission check. The allocation is an editorial practice plan, not 37signals' official schedule.
| Scope choice | Include now | Why |
|---|---|---|
| Create a request | Yes | It establishes the user object and validates input. |
| List requests and filter by status | Yes | A reviewer can see that the work serves a real workflow. |
| Resolve and reopen | Yes | The state transition gives a meaningful edge case. |
| Email notifications | No | It adds service credentials and failure paths beyond the core sample. |
| Authentication and permissions | No, unless requested | Invented security scope could consume the entire timebox. |
| Highly generic plugin architecture | No | It increases abstraction before there is a second use case. |
The “no” items are not universally unimportant. They are deferred because this exercise has a small budget. A real prompt may require authentication or deployment; then those become requirements. The point is to make scope a visible decision tied to the user's path, not to copy this list into an unrelated assignment.
Make a small project complete
Define what “done” means before building. For the status board, done could be: a new request with a nonempty title appears in the open list; resolving it with an optional note moves it to the resolved filter; reopening it restores it to open; invalid input receives a clear message; data remains after restarting the app if persistence is part of the chosen implementation. This is a better target than “implement a board” because every condition is observable.
Start with the simplest data model that expresses the behavior: request ID, title, description, status, optional resolution note, created time, and perhaps updated time. Add fields only when a stated behavior needs them. A single status enum can prevent accidental states such as done-ish or closed2. The interface can be plain. A clear interaction path and sensible empty state often say more about product judgment than decorative styling around incomplete functionality.
Choose a familiar stack so setup does not consume the budget. If the assignment specifies a stack, follow it. If it permits choice, prefer one you can run and explain. Be cautious about a dependency that solves a trivial problem but makes the reviewer install a large toolchain. Conversely, do not avoid a standard framework solely to appear clever if it makes the project harder to understand. State the choice and its cost in one sentence.
Test the risky boundaries. For this exercise: empty title rejected, resolution idempotent or clearly handled, filter returns only the requested status, and persisted data can be loaded again. You do not need a giant suite that restates every line of code. One focused integration or request-level test of the create–resolve–filter path may be more convincing than many isolated mocks. Run the app from the documented command in a clean environment and fix any missing setup instructions.
The 2023 intern account says an assignment was later discussed in a technical interview, which makes explainability important. Do not hide the only interesting decision behind a generic library and then provide no rationale. If you used a generated scaffold or code assistant and the prompt permits it, disclose that accurately and ensure you understand every important part. If the prompt prohibits a tool, follow that instruction. An answer that you cannot defend in conversation is not finished work.
Write a compact design note that a reviewer can use
A README should help someone run, inspect, and question the project. Put setup and test commands near the top, then the intended user path. Add a small “decisions and limits” section. For the status board, it might say: “I used SQLite for a single-process sample because it gives persistence without a service dependency. I kept one status transition endpoint and validate the transition server-side. I did not add user accounts; this sample is single-user and should not be deployed as a shared production app. With more time, I would add authorization before multi-user access.”
That note is stronger than “built with modern best practices.” It identifies the specific assumption, the rationale, the risk it creates, and the next step that would address it. If you chose a file instead of SQLite, explain how you avoid corrupt writes or explicitly state that concurrency is out of scope. If you skipped persistence, do not quietly imply durability; explain that the current sample keeps state in memory and why.
Include one short test observation: “I ran the create–resolve–filter test and manually restarted the app to confirm saved data loaded.” Only claim checks you performed. A README containing imaginary performance numbers or a screenshot of an untested happy path reduces trust. If you attempted a feature and it remains incomplete, mark it clearly rather than suggesting that it works.
Prepare to explain the trade-offs live
After submitting, rehearse a five-minute walkthrough: user problem, chosen scope, data flow, one implementation decision, one test, and one limitation. Then ask yourself how the design would change under a new condition. What if requests need multiple owners? What if two people resolve the same item? What if the title contains markup? What if the app must be accessible to keyboard-only users? You do not need to implement every variant; you need to reason about consequences.
The 2025 37signals podcast discusses looking at the work and asking candidates what they would do differently with more time. Your answer should be specific: “I would add optimistic concurrency to avoid overwriting another agent's status change” is better than “I would make it scalable.” If your exercise is single-user, say that the concurrency issue is hypothetical and would matter only after a product requirement changed. This shows restraint as well as technical awareness.
You should also be able to defend a trade-off you made. For example: “I kept the filter server-side because I wanted one source of truth for status and a small client. That costs a request per filter change, which is acceptable for this sample. If offline interaction became a requirement, I would revisit it.” The reasoning matters more than the particular side you chose.
Candidate reports: this guide uses no independent same-cycle reports to infer a current prompt or scorecard. A public account of a previous applicant's exact task, even if found, would not necessarily authorize reuse or disclose what a new applicant should build. Use the actual invitation; do not seek leaked prompts.
Five practice questions for the discussion after the work
Explain how each prompt would change your tiny project's design or README.
| Practice question | What to rehearse |
|---|---|
| Respond to a Material Scope Change Mid-Project | Scope change |
| How do you prioritize requirements | Requirement priority |
| How would you prioritize and test features? | Testing priority |
| Debug Feature Updates in a Laptop Management CLI | Focused debugging |
| Debug Validation Error Aggregation | Validation boundary |
When you have the real assignment, choose a complete user path, write a short definition of done, and stop adding features early enough to run the app and describe its limits. A small project with a clear boundary gives the reviewer something concrete to discuss.
Sources and Further Reading
- 37signals, “Titles, tenure, and paths don't matter” (REWORK, August 2025) — dated official discussion of programmer work samples and the four-to-six-hour example.
- 37signals Dev, “Web programming internship” (August 2023) — dated employee account of a small assignment and follow-up technical conversation.
- 37signals, “Hire Managers of One” (REWORK, February 2023) — dated official discussion of self-directed work and sample projects.