NewYour coding agent can read the release notes before it upgrades.Set up the MCP server →
Go modules · #2720 by repository stars
Last release 1 years ago
13 May 2025
Ships unpredictably
gaps range from 2 weeks to 1.7 years
Nearly every release is documented
notes for 16 of 16 stable releases
Nothing withdrawn
no release was ever pulled
5 years old
34 releases · first in 2021
One column per quarter.
The sse.Server logging and session handling were revamped to have more familiar, more flexible and less error prone interfaces for users. Some bugs we
The sse.Server logging and session handling were revamped to have more familiar, more flexible and less error prone interfaces for users. Some bugs were also fixed.
Logger and LogLevel enum have been removed. Server.Logger has transitioned to the standard slog library for better compatibility with the ecosystemServer.Logger is now of type func(r *http.Request) *slog.Logger instead of sse.Logger – it is possible to customize the logger on a per-request basis, by for example retrieving it from the context.Server.OnSession signature changed from func(s *Session) (Subscription, bool) to func(w http.ResponseWriter, r *http.Request) (topics []string, accepted bool) – its initial role was to essentially just provide the topics, so the need to fiddle with Session and Subscription was redundant anywayJoe.Subscribe now always returns ErrProviderClosed when a Joe instance is closed while subscriptions are active. Previously it would return it only if Joe was already shut down before subscribing.Joe will print a stack trace for Replayer panics.sse.Session doesn't write the header explicitly anymore. This would cause a http: superfluous response.WriteHeader call warning being logged when sse.Server.OnSession writes a response code itself when accepting a session. The change was initially introduced to remove the warning for users of certain external libraries (see #41) but this is the issue of the external library, not of go-sse. If you encounter this warning when using an external library, write the response code yourself in the HTTP handler before subscribing the sse.Session, as described in the linked discussion.Joe causing a channel double close in an edge case scenario (see #50, see code for details)slog and adding it to the library!Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
If you're working with LLMs in Go this update will make you happy! sse.Read is now a thing – it just parses all events from an io.Reader . Use it with
If you're working with LLMs in Go this update will make you happy! sse.Read is now a thing – it just parses all events from an io.Reader. Use it with your response bodies and forget about any sse.Client configuration. It also makes use of the new Go 1.23 iterators to keep your code neat and tidy.
Read and ReadConfigThis is the replayer update. Oh, what is a "replayer"? It's how we call replay providers starting with this version! Anyway, besides renaming, this up
This is the replayer update. Oh, what is a "replayer"? It's how we call replay providers starting with this version! Anyway, besides renaming, this update removes many replaying bugs, improves performance, robustness and error handling and better defines expected behavior for ReplayProviders... err, Replayers.
More such overhauls are planned. I'm leaving it up to you to guess which comes next – the server or the client? ;)
FiniteReplayer.{Count, AutoIDs} – use the constructor instead.ValidReplayer.{TTL, AutoIDs} – use the constructor instead.ReplayProvider and related entities are renamed to just Replayer. go-sse strives to have a minimal and expressive API, and minimal and expressive names are an important step in that direction. The changelog will use the new names onwards.FiniteReplayer is now able to replay events only if the event with the LastEventID provided by the client is still buffered. Previously if the LastEventID was that of the latest removed event, events would still be replayed. This detail added complexity to the implementation without an apparent significant win, so it was dropped.FiniteReplayer.GCInterval should be set to 0 now in order to disable GC.Replayer.Put now returns an error instead of being required to panic. Read the method documentation for more info. Joe also propagates this error through Joe.Publish.Joe does not log replayer panics to the console anymore. Handle these panics inside the replay provider itself.NewFiniteReplayer constructorNewValidReplayer constructorConnection.BufferFiniteReplayer doesn't leak memory anymore and respects the stored messages count it was given. Previously when a new message was put after the messages count was reached and some other messages were removed, the total messages count would grow unexpectedly and FiniteReplayer would store and replay more events than it was configured to.ValidReplayer was also susceptible to a similar memory leak, which is also fixed now.sse.Session now writes the header explicitly when upgrading.Nothing published for this version
Nothing published for this version
Client read buffer configuration
Client read buffer configuration
Use circular buffer in FiniteReplayProvider
Use circular buffer in FiniteReplayProvider
This version removes all external dependencies of go-sse . All our bugs are belong to us! It also does some API and documentation cleanups.
This version removes all external dependencies of go-sse. All our bugs are belong to us! It also does some API and documentation cleanups.
Client.DefautReconnectionTime, Client.MaxRetries have been replaced with the new Client.Backoff configuration field. See the Added section for more info.ErrReplayFailed is removed from the public API.ReplayProviderWithGC and Joe.ReplayGCInterval are no more. The responsibility for garbage collection is assigned to the replay providers.Server.Logger is now of a new type: the Logger interface. The dependency on x/exp/slog is removed. This opens up the possibility to adapt any existing logger to be usable with Server.Backoff configuration as follows:sse.Backoff{
InitialInterval: 5 * time.Second, // currently 500ms
Multiplier: 1.5, // currently the same
Jitter: 0.5, // currently the same
MaxInterval: 60 * time.Second, // currently unbounded
MaxElapsedDuration: 15 * time.Minute, // currently unbounded
MaxRetries: -1, // previously no retries by default, currently unbounded
}Joe now accepts new subscriptions even if replay providers panic (previously ErrReplayFailed would be returned).Server.ServeHTTP panics if a custom OnSession handler returns a Subscription with 0 topicsLogger interface, LogLevel type, and LogLevel(Info|Warn|Error) values.Backoff and Client.Backoff – the backoff strategy is now fully configurable. See the code documentation for info.ValidReplayProvider.GCInterval, to configure at which interval expired events should be cleaned up.Nothing published for this version
Nothing published for this version
This version overhauls connection retry and fixes the connection event dispatch order issue. Some internal changes to Joe were also made, which makes
This version overhauls connection retry and fixes the connection event dispatch order issue. Some internal changes to Joe were also made, which makes it faster and more resilient.
ConnectionError.TemporaryConnectionError.TimeoutTimeout and Temporary interfaces are not used anymore – the client makes no assumptions and retries on every network or response read error. The only cases when Connection.Connect returns now are either when there are no more retries left (when the number is not infinite), or when the request context was cancelled.*url.Errors that occur on the HTTP request are now unwrapped and their cause is put inside a ConnectionError.Connection.Connect doesn't suppress any errors anymore: the request context errors are returned as is, all other errors are wrapped inside ConnectionError.ConnectionError. With this change, all errors other than the context errors are wrapped inside ConnectionError.ReplayProvider method panics when called by Joe, instead of closing itself completely it just stops replaying, putting or GC-ing messages to upcoming clients. Joe continues to function as if no replay provider was given. A stack trace is printed to stderr when such a panic occurs.Nothing published for this version
This version brings a number of refactors to the server-side tooling the library offers. Constructors and construction related types are removed, for
This version brings a number of refactors to the server-side tooling the library offers. Constructors and construction related types are removed, for ease of use and reduced API size, concerns regarding topics and expiry were separated from Message, logging of the Server is upgraded to structured logging and messages can be now published to multiple topics at once. Request upgrading has also been refactored to provide a more functional API, and the Server logic can now be customized without having to create a distinct handler.
Message.ExpiresAt is no more.Message.Topic is no more. See the changes to Server, Provider and ReplayProvider for handling topics – you can now publish a message to multiple topics at once.Message.Writer is no more. The API was redundant – one can achieve the same using strings.Builder and Message.AppendData. See the MessageWriter example for more.NewValidReplayProvider is no more.NewFiniteReplayProvider is no more.NewJoe is no more.JoeConfig is no more.Server.Subscribe is no more – it never made sense.Server.Provider is no more.NewServer, ServerOption and friends are no more.Logger interface and the capability of the Server to use types that implement Logger as logging systems is removed.SubscriptionCallback is no more (see the change to the Subscription type in the "Changed" section).ValidReplayProvider constructor was removed, the fields ValidReplayProvider.{TTL,AutoIDs} were added for configuration.FiniteReplayProvider constructor was removed, the fields FiniteReplayProvider.{Count,AutoIDs} were added for configuration.Joe constructor was removed, the fields Joe.{ReplayProvider,ReplayGCInterval} were added for configuration.Server constructor was removed, the field Server.Provider was added for configuration.MessageWriter interface; used by providers to send messages and implemented by Session (previously named Request).ResponseWriter interface, which is a http.ResponseWriter augmented with a Flush method.ValidReplayProvider has a new field Now which allows providing a custom current time getter, like time.Now, to the provider. Enables deterministic testing of dependents on ValidReplayProvider.Server.OnSession field, which enables customization of Server's response and subscriptions.Server.Logger field, which enables structured logging with logger retrieved from the request and customizable config of logged information.ReplayProvider.Put takes a simple *Message and returns a *Message, instead of changing the *Message to which the **Message parameter points.Message doesn't hold the topic itself anymore. If the Message cannot be put, the method must now panic – see documentation for info.Message.ExpiresAt is removed, the ValidReplayProvider sets the expiry itself.Server.Publish now takes a list of topics.Provider.Publish now takes a non-empty slice of topics.ReplayProvider.Put now takes a non-empty slice of topics.Provider.Stop is now Provider.Shutdown and takes now a context.Context as a parameter.Server.Shutdown takes now a context.Context as a parameter.Request is now named Session and exposes the HTTP request, response writer, and the last event ID of the request.Flush is added to Session; messages are no longer flushed by default, which allows providers, replay providers to batch send messages.Upgrade now takes an *http.Request as its second parameter.Subscription now has a Client field of type MessageWriter instead of a Callback.Subscription change, Provider.Subscribe and ReplayProvider.Replay now report message sending errors.If you have any suggestions, things are breaking, need some help or want to show appreciation, please and feel free to open an issue, say somthing in the Discussion of this release, or text me in private using the socials on my profile!
The new Message.Writer – write to the Message as if it is an io.Writer .
Message.Writer – write to the Message as if it is an io.Writer.Message.UnmarshalText now strips the leading Unicode BOM, if it exists, as per the specification.Nothing published for this version
Message.WriteTo now writes nothing if Message is empty.
Message.WriteTo now writes nothing if Message is empty.Message.WriteTo does not attempt to write the retry field if Message.Retry is not at least 1ms.NewType error message is updated to say "event type", not "event name".If you have any suggestions, things are breaking, need some help or want to show appreciation, please and feel free to open an issue or text me in private using the socials on my profile!
This version comes with a series of internal refactorings that improve code readability and performance. It also replaces usage of []byte for event da
This version comes with a series of internal refactorings that improve code readability and performance. It also replaces usage of []byte for event data with string – SSE is a UTF-8 encoded text-based protocol, so raw bytes never made sense. This migration improves code safety (less unsafe usage and less worry about ownership) and reduces the memory footprint of some objects.
Creating events on the server is also revised – fields that required getters and setters, apart from data and comments, are now simple public fields on the sse.Message struct.
Across the codebase, to refer to the value of the event field the name "event type" is used, which is the nomenclature used in the SSE specification.
Documentation and examples were also fixed and improved.
sse.EventName type, which holds valid values for the event field, together with constructors (sse.Name and sse.NewName).sse.Message: AppendText was removed, as part of the migration from byte slices to strings. SSE is a UTF-8 encoded text-based protocol – raw bytes never made sense.sse.Message: AppendData takes strings instead of []byte.sse.Message: Comment is now named AppendComment, for consistency with AppendData.sse.Message: The message's expiration is not reset anymore by UnmarshalText.sse.Message: UnmarshalText now unmarshals comments as well.sse.Message: WriteTo (and MarshalText and String as a result) replaces all newline sequences in data with LF.sse.Message: The Expiry getter and SetExpiresAt, SetTTL setters are replaced by the public field ExpiresAt.sse.Message: Event ID getter and setter are replaced by the public ID field.sse.Message: Event type (previously named Name) getter and setter are replaced by the public Type field.sse.Message: The retry field value is now a public field on the struct. As a byproduct, WriteTo will now make 1 allocation when writing events with the retry field set.sse.NewEventID is now sse.NewID, and sse.MustEventID is sse.ID.sse.Event: The Data field is now of type string, not []byte.sse.Event: The Name field is now named Type.sse.Message: Clone now copies the topic of the message to the new value.sse.Message: ID fields that contain NUL characters are now ignored, as required by the spec, in UnmarshalText.Messages longer than 4096 bytes are no longer being dropped ([#2], thanks [@aldld])
Nothing published for this version
Get the event name of a Message
### Added - Set a custom logger for Server
Server does not set any other headers besides Content-Type.
Content-Type.Content-Type parameters when checking if the response's content type is text/event-stream.Nothing published for this version
ReplayProviderWithGC interface, which must be satisfied by replay providers that must be cleaned up periodically.
Text/JSON marshalers and unmarshalers, and SQL scanners and valuers for the EventID type (previously event.ID).
client.Error - sse.ConnectionErrorevent.Event - sse.Message (previous server.Message is removed, see next change)event.ID - sse.EventIDevent.NewID - sse.NewEventIDevent.MustID - sse.MustEventIDserver.Connection - sse.UpgradedRequestserver.NewConnection - sse.Upgradeserver.ErrUnsupported - sse.ErrUpgradeUnsupportedserver.New - sse.NewServer.event.Event is merged with server.Message, becoming sse.Message. This affects the sse.Server.Publish function, which doesn't take a topic parameter anymore.Provider as a parameter. It instead takes multiple optional ServerOptions. The WithProvider option is now used to pass custom providers to the server.ReplayProvider interface's Put method now takes a **Message instead of a *Message. This change also affects the replay providers in this package: ValidReplayProvider and FiniteReplayProvider.Provider interface's Publish method now takes a *Message instead of a Message. This change also affects Joe, the provider in this package.UpgradedRequest's Send now method takes a *Message as parameter.[@aldld]: https://github.com/aldld
Nothing published for this version
Nothing published for this version
Nothing published for this version
Your coding agent can read these notes before it upgrades. Set up the MCP server →