I don't understand why there need to be two tables in the database. It seems that a key-value storage is sufficient -- the key is the hash of the text and the value contains the text, the upload time, and the expiration period.

What is in my mind is that we need a Web server, which accepts the uploaded text and saves the text into the above key-value storage. We also need a daemon, which scans over the storage pass and pass. For each item, if it is expired (current_time >= upload_time + expiration_period), the daemon removes the item; otherwise, the daemon creates a timer to wake it up at the expiration time to remove the item.

package main import ( "timer" ) type TimeoutHandler struct { actionList map[string]int nextPass chan int } func NewTimeoutHandler() *TimeoutHandler { return &TimeoutHandler{ actionList: make(map[string]int), nextPass: make(chan int, 100), } } func (th *TimeoutHandler) RemoveItemWhenExpired(string key, Value value) { th.actionList[key] = 1 t := timer.NewTimer(value.ExpireTime) go func(key string) { <-t.C storage.Delete(key) delete(th.actionList, key) if len(th.actionList) <= 0 { th.nextPass <- 1 // trigger the scan of the next pass. } t.Close() }(key) } func (th *TimeoutHandler) Run() { for { for s := storage.NewScanner(); !s.Done(); s.Next() { th.RemoveItemWhenExpired(s.Key(), s.Value()) } <-th.nextPass } } func main() { th := NewTimeoutHandler() th.Run() }