Senior · Architecture and systems
A rolling deploy and an old event replay
Version two renames a JSON/database field. Version one workers are still running and retained events will be replayed next week. How do you deploy?
Try explaining this aloud before opening the answer. State your assumptions and trace a boundary case.
package main
import (
"encoding/json"
"fmt"
)
type Wire struct {
Name string `json:"name"`
DisplayName string `json:"display_name,omitempty"`
}
func name(w Wire) string {
if w.DisplayName != "" {
return w.DisplayName
}
return w.Name
}
func main() {
for _, raw := range []string{`{"name":"Ada"}`, `{"name":"Ada","display_name":"A. Lovelace"}`} {
var w Wire
if err := json.Unmarshal([]byte(raw), &w); err != nil {
panic(err)
}
fmt.Println(name(w))
}
}Reveal a strong answer
A rolling deployment is a period with multiple versions, not an instantaneous replacement. The database, producers, consumers and cached clients may all run different code. An additive change is useful only if old readers tolerate it and the new writer does not destroy information they still need. Plan compatibility as a sequence with observable exit conditions.
First deploy readers that understand both shapes. Then introduce the new field and migrate stored data with a restartable cursor. Measure old-field use before removing it. Give events explicit schema contracts and keep captured old payloads as fixtures. Review semantic changes too: changing units, default timeouts or authorization can break a client without changing a Go type. The new reader accepts the old name field and prefers the additive display_name field when present. This is a migration model, not a universal rule to accept arbitrary input: strict external API validation and backward-compatible internal event readers can require different policies. Presence and an empty string may need a pointer or explicit optional type.
A rename performed as drop-old/add-new in one release breaks old binaries during rollout and rollback. Avoid dual writes without a stated source of truth and reconciliation policy. Database index creation and long backfills also need operational budgets. Test old writer/new reader, new writer/old reader, rollback and replay of retained events before declaring the migration complete.
Common trap
A source-level rename and green compilation do not prove mixed-version or replay compatibility.
Try it
Write the sequence of compatible reader deployment, writer change, migration, observation and removal; include rollback.
Worked solution
Expand readers to understand both representations first. Add compatible writes under a stated source-of-truth policy, migrate stored records with restartable checkpoints and measure remaining old-field consumers. Remove the old contract only when the rollout, rollback and retained-event replay policy permits it. Keep captured old/new payload fixtures and test semantic changes such as units and defaults, not only successful JSON decoding.
Change the constraint
How would strict external input validation differ from tolerant internal event readers?
How did you do?
Self-assessment, not a compiler pass or interview score. Explain the reasoning unaided before marking understood.
Not marked. Progress stays on this browser, separate from course completion.
Primary references
Checked 2026-10-28. Use documentation for your pinned runtime, driver and tool version.