Release Notes (2.0.x)
Apache Pekko 2.0.x releases support Java 17 and above.
2.0.0
Apache Pekko 2.0.0 is a new major release. Do not assume binary compatibility with Pekko 1.x: libraries built against Pekko 1.x need to be rebuilt against Pekko 2.0.0, and some code will need source changes. Please read the Migration Guide before upgrading.
It could take months for the other Pekko modules, such as Pekko HTTP, Pekko Connectors, Pekko gRPC, Pekko Management and the persistence plugins, to have 2.0.0 releases. Until then, users might be able to use the 2.0.0 milestone releases of those modules with Pekko 2.0.0, but you should test very carefully before relying on this in production.
The changes in this release were previewed in a series of milestone releases. See the GitHub milestones for 2.0.0-M1, 2.0.0-M2, 2.0.0-M3, 2.0.0-M4 and 2.0.0-M5 for a fuller list of changes.
Some of the bug fixes listed below have also been backported to Pekko 1.x releases.
Main changes
- Java 17 is the new minimum version (Java 8 and 11 are no longer supported) (#1730, PR1967)
- Scala 2.12 support has been dropped. Pekko 2.0.0 is published for Scala 2.13 and Scala 3 (#39, PR1986)
- A lot of code that was deprecated in Pekko 1.x (and in Akka before that) has been removed - see the Removed section below
- Big change for Java DSL users due to the removal of
pekko.japi.Function(and related classes, such aspekko.japi.function.FIandJAPI) in favour ofpekko.japi.function.Functionand the otherpekko.japi.functiontypes. Lambdas should recompile ok but if you declared variables or functions explicitly, then you may need to change your imports (PR2001, PR2064, PR2078, PR2079, PR2143, PR2198) - Java APIs no longer leak Scala types: Scala
Future,Option,Tuple2and Scala collections have been replaced withCompletionStage,Optional,pekko.japi.Pairand Java collections in a number of Java DSL methods, including the pekko-persistence Java APIs (PR1419, PR2007, PR2009, PR2092, #2086, PR3378, PR3388, PR3677) - Added many Akka changes that have recently become Apache Licensed (up to and including Akka 2.9.0) - see the Ported from Akka section below
sun.misc.Unsafeis no longer used. The code has been migrated to use VarHandles (PR1892, PR1894, PR1990, PR1995, PR3007, PR3008)- Reflection usage in core modules has been replaced with MethodHandles/VarHandles where possible (PR3300, PR3312)
- New pekko-serialization-jackson3 module. Users who are happy with pekko-serialization-jackson, which uses Jackson 2, can stick with that (PR2348)
- Switch to
PEKKas the default magic header in pekko-remote Artery comms. See Changing TCP magic header for what this means for rolling updates (PR3425) - Java 21 and 25 support improvements, including virtual thread support for more dispatcher types and JDK-aware ForkJoinPool tuning (#2232, PR2169, PR2242, PR2871, PR2890)
- Added JSpecify nullness annotations to the Java DSL APIs of streams, persistence, actor-typed, cluster-sharding-typed and testkit (#2563, PR2617, PR2850, PR3380)
- A number of security hardening changes - see the Security Hardening section below
- A number of configuration defaults have changed. See the Configuration Changes section of the Migration Guide
Upgrade notes
Please read the Migration Guide before upgrading. It covers the breaking API changes, dependency changes (such as the Agrona 2.x --add-opens requirement) and the configuration defaults that have changed in Pekko 2.0.0.
Unless already waiting for the peer’s close_notify, cancelling a TLS operator’s transport output now reports SessionTruncated on its plaintext output if a session was established and the peer’s close_notify has not been processed, including when no inbound data is buffered or a renegotiation is in progress (PR3740). Previously this path could complete silently after discarding received records. Consumers using the TLS BidiFlow directly must handle SessionTruncated as well as SessionBytes. The Scala and Java Tcp.bindWithTls and Tcp.outgoingConnectionWithTls APIs filter out this signal and continue to expose ByteString streams. The final signal obeys backpressure; cancel the plaintext output too if it will no longer be consumed. See Stream IO for details.
Bug Fixes
- Replaying a replicated event sourced actor from a snapshot caused a bug (PR2372)
- Emit
DeletedDurableStatefor deleted durable state objects (PR2397) - Fix close being called in cancel for statefulMap (PR2365, PR2385)
- Fix recoverWith on a failed stage (PR2631, PR2674, PR2712)
- Fix Source.combine with a single source and type-transforming fan-in strategies (PR2726)
- Release lease on shard stop (PR2738)
- Fix ProducerController crash on restart with an empty unconfirmed buffer (durable queue) (#2760, PR2762)
- Handle unexpected stop of the TLS actor gracefully (PR2801)
- Fix ByteString1C serialization to use a SerializationProxy (PR2929)
- Harden async DNS request id handling (PR2960)
- High concurrency issues introduced when switching from
sun.misc.Unsafeto VarHandles (PR3007, PR3008) - MapAsyncPartitioned fixes: ordered stage completion after trailing resumed failures, parallel processing preserving order within a partition and a demand-resume deadlock (PR3009, #2886, PR3365)
- Await in-flight completion on partner termination in SinkRef (PR3016)
- Prevent double materialization of SourceRef and SinkRef (PR3114)
- Release references to completed stage logics and to the initial interpreter shell in GraphInterpreter to avoid memory retention (PR3030, PR3031, #3243)
- Discard stale ReceiveTimeout after cancelReceiveTimeout to avoid NPE in actor-typed (PR3086)
- Clean up stopped FSM transition listeners (PR3096)
- Preserve throttler tokens on failed writes (PR3097)
- Initialize timer stage deadlines in preStart instead of at construction (PR3111)
- Fix the current message reported to supervision in timer stages (PR3294)
- Fix close handling in unfoldResource and unfoldResourceAsync (avoid double close and delay close until a pending read completes) (PR3157, PR3172)
- Classic remoting robustness fixes: ignore stale ACKs, harden EndpointReader against dispatch errors, resume the reader after a failed handoff and buffer messages during passive handoff (PR3158, PR3166, PR3173, PR3205, PR3361)
- Validate the full UniqueAddress in Artery system message ACK/NACK handling (PR3175)
- Bound Artery stream shutdown (PR3317)
- Use
Locale.ROOTfortoLowerCase/toUpperCasecalls (PR3159) - Avoid NPE in the outbound TCP stage when upstream finishes before connect (PR3259)
- Close unregistered TCP channels on setup failure (PR3273)
- Suppress dead-letter logging during a terminating shutdown when disabled (PR3262)
- Expand Array arguments in MarkerLoggingAdapter log templates (PR3263)
- Deliver stashed timer messages for UnboundedStash and UnrestrictedStash (PR3264, #3265)
- Return a proper non-cancelled Cancellable from StubbedActorContext.scheduleOnce (PR3268)
- Fix deferred TLS output handling on inbound close and abort the TLS transport on session verification failure (PR3323, PR3324)
- Fix reentrant BatchingExecutor execution (PR3331)
- Notify BroadcastHub and PartitionHub consumers on materializer shutdown (#3345, PR3346, PR3347)
- Enforce resizer bounds and minimum pool size for AdjustPoolSize, including in ClusterRouterPool (#3253, PR3364, PR3393)
- Support
java.math.BigInteger/BigDecimalin cluster-metrics (#3385, PR3382) - Invoke lifecycle signal handlers during snapshot recovery (PR3358)
- Stop PersistentActor by default when the RecoveryCompleted handler fails (PR3359)
- Filter messages from the remember-entities store (PR3411)
- Preserve StageActor demand across fused streams (#3459, PR3461)
- Handle post-Java 8 constant pool entries in LineNumbers (PR3465)
- Make AbstractPersistentActorWithTimers and AbstractFSMWithStash subclassable from Java when using Scala 3 (PR3475)
- Use a Seq rather than a Set to hold TCP magic ByteStrings (PR3484)
- Stop cluster sharding entities stuck in passivation after a timeout (PR3573)
- Stop handing a reused
Mailboxobject to the fork-join dispatcher, which could permanently damage a ForkJoinPool work queue or stop a mailbox from running again.Mailboxno longer extendsForkJoinTask(#3613, #3620, PR3621, PR3628, PR3668) - Keep colliding virtual nodes in ConsistentHash, so the ring no longer depends on the order in which nodes were added or removed. Routing only changes for keys that land on a colliding ring position, but during a rolling update nodes on 1.x and 2.x could route those few keys differently (PR3611)
- Resolve a
LogSourceforgetClassresults on Scala 3, soLogging(system, getClass)compiles (#1538, PR3609) - Allow overriding
testKitwith avalinScalaTestWithActorTestKit(#1140, PR3610) - Keep the
StashBufferImplinstrumentation hooks from being inlined by the Scala 2.13 optimizer (PR3616) - Stop dispatcher failure reporting from recursing into a
StackOverflowError(#3613, PR3622)
Security Hardening
- Pekko Remote TLS: optional hostname verification for classic remoting, warnings when hostname verification is not enabled or when TLS is not used, a new keystore-password config, eager SSLContext initialization in Artery so that misconfiguration fails fast and support for multiple certificates in the rotating keys engine
ca-cert-file(PR3164, PR3200, PR3397, PR3398, PR3400, PR3479, PR3528) - Jackson
JsonTypeInfo.Id.MINIMAL_CLASSis now treated as dangerous, likeId.CLASS(PR3304) - Resolve, check and parse manifests more carefully in the Jackson serializers (PR3503)
- New
max-decompressed-sizelimit for Jackson payload decompression and for other compressed payloads (defaults to unlimited for Jackson) (PR3491, PR3502, #3504, PR3515, PR3597) - Support
unlimitedfor the Jackson stream-read constraints (PR3522) - Bound inbound Artery TCP frame length at framing (PR3492, PR3524)
- Bound nesting depth when deserializing enclosed payloads (PR3500)
- Bound the number of entries in an Artery compression table advertisement (PR3510)
- Bound compression-pointer hops in DNS name parsing (PR3490)
- Don’t resolve HOCON includes in config that arrived in a message (PR3505)
- Match actor selection wildcards without backtracking (PR3506)
- Reject messages whose parallel repeated protobuf fields disagree in length (PR3507)
- Bounds check the lookup table indexes in cluster gossip (PR3508)
- Don’t dereference a null superclass in the protobuf allow list check (PR3509)
- Bound persistence event replay batches (PR3325)
- Add
maxTotalBufferSizeto MergeHub for an aggregate queue bound (PR3392)
Ported from Akka
These changes were copied from Akka releases (up to and including Akka 2.9.0) that are now available under the Apache License, version 2.0.
- Unpersistent versions of persistent behaviors for testing, renamed to
PersistenceProbeBehavior(PR2456, PR2494) - Custom stash support in persistence-typed (PR2433)
- Asking support in the typed BehaviorTestKit (PR2450, PR2453)
- ShardedDaemonProcess: throttle keep-alive messages and limit them to a subset of nodes (PR2734)
- Distributed Data: wildcard prefix subscriptions in the Replicator (PR2735)
- Include roundtrip latency and sequence number in the heartbeat debug log (PR2736)
- Optimize PropsAdapter, typed actor context and system adapter (PR2743, PR2750)
- Auto-select SRV lookup for the name lookup if the entry looks like an SRV name (PR2745)
- Run the DurableStateBehavior delete effect asynchronously like persist (PR2752)
- Use ClusterShuttingDown in the Distributed Data Replicator (PR2765)
- Add ScheduledClock to reduce nanoTime overhead in recency-based passivation (PR2766)
- Snapshot retention: only-one-snapshot optimization and only one retention cycle in progress at a time (PR2767, PR2797)
- Improve the cluster sharding StopShards coordinator command and fix the coordinator role (PR2783, PR2918)
- Disable ClusterShardingHealthCheck after a configured duration post member-up (PR2785)
- Remember entities throttling per region instead of per shard and improved DData remember entities logging and consistency (PR2786, PR2799)
- Improve error message for actorOf on a typed ActorSystem (PR2798)
- Fine-grained stream error logging control (PR2805)
- Add filtered, source and tags fields to typed EventEnvelope, EventsByPersistenceIdTyped queries and
withTaggerForState(PR2807, PR2920) - Support for external transport of replicated events in Replicated Event Sourcing (PR2808)
- DnsResolutionActor and in-flight request deduplication (PR2919)
- Initialize the DistributedData extension from ExternalShardAllocationStrategy (PR2923)
- Make it possible to define the cluster
appVersionlater (PR2947) - Support ActorSystem/ClassicActorSystemProvider serializer constructors and improve the error message (PR2948)
- Runtime plugin configuration for DurableState (PR3058)
- Consistent-hashing shard allocation strategy (PR3270)
- Include the exception type in StatusReply toString when not text (PR3271)
- FilteredPayload placeholder for filtered journal events (PR3275)
- Scalable fan-out persistence query abstraction (
EventsBySliceFirehoseQuery) andEventsBySliceStartingFromSnapshotsQuery(PR3277) - Include sourceThread in the typed actor MDC (PR3357)
- Other Akka 2.8.4 changes (PR3432)
- Support default attributes on materializers (PR3647)
- Define a custom lease name for Cluster Sharding and Cluster Singleton (PR3648)
- Add
withmethods to the typed queryEventEnvelope(PR3646) - Predefined
JsonSerializableandCborSerializablemarker traits in pekko-serialization-jackson and pekko-serialization-jackson3, bound tojackson-jsonandjackson-cbor(PR3649, PR3666) - Bind ScalaPB messages to the protobuf serializer when ScalaPB is on the classpath (PR3651)
- Add
SerializedEventfor writing events that are already serialized (PR3650)
Additions
- Add
ActorSystem.terminateAndAwaitandActorSystem.close(PR2096, PR2486) - Add
UntypedAbstractActorWithStash,UntypedAbstractActorWithUnboundedStashandUntypedAbstractActorWithUnrestrictedStash(PR2097) - Add actor-typed Java DSL
AbstractMatchingBehavior(#2108, PR2379) - Add logging variants for the Java DSL stash and timer actor base classes (#2520, PR3387)
- Add the timeout duration to the
ReceiveTimeoutmessage (PR3399) - Add
andThenandcomposetopekko.japi.function.Function(#2144, PR2147) - Add a throwing boolean supplier,
sneakyThrowandOptionalUtilJava utilities (PR2199, PR2218, PR2464) - Add
CompletionStagesutility and maketimeoutCompletionStage/afterCompletionStageaccept Java Duration (PR2060, PR2063, PR2067) - Add
StatusReply.fromTryandStatusReply.fromCallable(PR2810, PR2812) - Add
JournalPersistFailedandJournalPersistRejectedsignals (PR1961) - Add an AsyncWriteJournal option for disabling the Resequencer (PR2027)
- Add
DurableStateBehaviorTestKit(PR3360) PersistenceTestKitReadJournaltag and slice queries support resuming from aTimestampOffset(#1765, PR3615)- The Java test kits now support JUnit Jupiter (JUnit 5 and 6). Pekko’s own Java tests have been migrated from JUnit 4 (#967, PR2289, PR2724, PR2865)
- Java DSL TestKit
shutdownActorSystemthat takes Java Duration params (#2226, PR2277) - Add virtualize support for thread-pool-executor (including the blocking IO dispatcher) and support setting the starting number of virtual threads (#2163, PR2169, PR2242)
- Make ForkJoinPool
minimum-runnableconfigurable and auto-tune it on JDK 25+ (PR2871, PR2890) - Support the
SO_REUSEPORTsocket option (PR2915) - Add
ByteString.endsWith,indexOfwith from and to, and makeByteString.copyToBuffer(buffer, offset)public (PR2271, PR2862, PR2946) - Add OSGi headers to pekko-pki and pekko-cluster-typed and compute OSGi imports for Pekko packages dynamically (PR2107, PR2112, PR2313)
- Add zstd compression to the Jackson serializers (
compression.algorithm = zstd). zstd-jni is an optional dependency that you need to add yourself (PR3641) - Add Scala 3.8 and 3.9 compatibility (Pekko is still published using Scala 3.3 LTS) (PR3072, PR3073, PR3074, PR3295, PR3303)
The Stream API has been updated to add some extra operators.
- Add
Sink.sourceandmaterializeIntoSourceoperators (#2222, PR2250, PR1831) - Add
Sink#countoperator (#2182, PR2244) - Add
onErrorResume(including Java DSL, SubFlow and SubSource variants) and more recover operators for the Java DSL (#2116, PR2120, PR2336, PR2337) - Add
onErrorContinueoperator (#2159, PR2322) - Add
doOnFirstoperator (#2183, PR2363) - Add
doOnCanceloperator (#2374, PR2375) - Add
gzipDecompressoperator, replacing the deprecatedgunzip(which has been removed) (PR2406) - Add
Source.fromOptionandmapOptionoperators (#2408, #2403, PR2413, PR2414) - Add
Source.itemsand an array basedSource.apply(#2416, PR2424, PR2428, PR2429) - Add
withContextoperators (PR3199) - Add an
alsoTooverload with configurable cancellation propagation (PR3127) - Add supervision strategy support to more operators that accept user functions (
groupedWeightedWithin,batch,expandandextrapolate) and log supervision Resume/Restart in mapAsync operators (#3110, PR3124, PR3180, PR3184, PR3185) - Add an opt-in GraphStage based TLS engine (the actor based implementation remains the default) (PR2878)
Changes
- Make
SubFlowandSubSourcefinal classes and switch the type parameter order ofUnfoldResourceSourceandUnfoldResourceSourceAsync(PR615, PR616, PR619) - Remove the unnecessary empty parameter list from
watchTermination(#2376, PR2378) - Change
Futures#findand otherFuturesmethods to return JavaCompletionStage(#2008, PR2009) - Stream Java DSL now uses
pekko.japi.functiontypes throughout (#2118, PR2143) - Fix the Java DSL
SourceWithContext/FlowWithContextshape to usepekko.japi.Pair(#2510, PR3388) - Replace
scala.Tuple2withpekko.japi.PairinFSMTransitionHandlerBuilder(PR3378) - Replace
immutable.Traversablein the public io and stream APIs (PR3467, PR3468) - Remove
ExecutorServiceFactoryProviderfromThreadPoolConfig(#2171, PR2175) - Replace CountMinSketch with FastFrequencySketch in Artery compression (PR3023)
- Replace the actor based fanout publisher runtime (
Sink.asPublisher(fanout = true)) with a GraphStage bridge (PR2874) - Remove the deprecated annotation from
recoverWithand undeprecate thegetFirst/getFirstAttributemethods (PR2119, PR3404) - Mark public sealed traits and abstract classes with
@DoNotInherit(#1270, PR3386) - Remove
@ApiMayChangefrom APIs that have proven stable, including the log markers,RotatingKeysSSLEngineProvider,ExternalShardAllocation,RetryFlow, theMaterializerStateAPI and the typed persistence query APIs (PR3607, PR3636, PR3656) - Remove the Akka 2.6.4 rolling-migration manifests from ClusterMessageSerializer (PR3516)
- ClusterShardingSettings: remove backward-compat passivation code (PR3026)
- Remove the
ssl-configdependency (#2125, PR2127, PR2359) - Remove usage of
SecurityManager(#1970, PR2106) - Use the better ByteBuffer cleaner available in Java 9+ (PR2020, PR2031)
- Code modernisation to use Java 17 language features and APIs (pattern matching instanceof, switch expressions, records, sealed types, collection factories, lambdas instead of anonymous inner classes) (#2083, #2201, PR2088, PR3188, PR3190, PR3191, PR3192, PR3193, PR3194, PR3379)
- Code modernisation for Scala 2.13 and Scala 3, using the standard
scala.jdkconverters instead of compat libraries (#2126, PR2205, PR2206, PR2236, PR3539) - Use
-Yfuture-lazy-valsfor Scala 3 builds (PR3059) - Fix many compiler, Scaladoc and Javadoc warnings (PR3283, PR3284, PR3285, PR3297, PR3330)
- Regenerated the protobuf source code using protoc 4.36 (PR2036, PR2335, PR3514)
- Validate legal files in packaged jars (PR3328)
- Many documentation improvements, including a list of configuration changes in the migration guide, docs for the jackson3 module, the JUnit Jupiter test kit, custom Durable State store plugins, migrating off the deprecated
Source.queueoverloads and stream operator reference pages for previously undocumented operators (PR2391, PR2468, PR3274, PR3513, PR3583, PR3585, #3589, PR3590, PR3605, PR3654, PR3661)
Performance
- SIMD within a register (SWAR) and VarHandle based ByteString search (
indexOf,lastIndexOf,indexOfSlice,contains) (#1264, #2150, PR2148, PR2306, PR2309, PR2838, PR2839, PR2863) - Other ByteString improvements: faster equality, concatenation, slicing, fragment lookup,
ByteStringBuilder.resultand multi-byte reads (PR2847, PR2924, PR3427, PR3428, PR3463, PR3471, PR3526) - Faster
UnsynchronizedByteArrayInputStreamusage (PR2300, PR3541) - Batch elements across internal async stream boundaries (PR3288, PR3296, #3459, PR3461)
- Optimize
Source.fromiterable,Source.future,Source.futureSourceandSource.applyfor Seq (PR2556, PR2560, PR2562) - Avoid substream materialization for value-presented sources in FlattenMerge and concat (PR2977, PR2978)
- GraphInterpreter hot path optimizations (PR2986, PR3119, PR3373)
- Stream materializer wiring and stage actor optimizations (PR3035, PR3062, PR3063)
- Optimize
Source.actorRefwith a direct-push fast path (PR3091) - Avoid Holder allocation in ordered mapAsync for already-completed futures (PR3018)
- Use an ArrayList in BroadcastHub (PR2262)
- Reduce receive-timeout state allocations and avoid type pollution (PR3332, PR3334)
- Validate actor path elements without
String.charAt(PR3542)
Removed
Much of the code that was deprecated in Pekko 1.x (and in Akka before that) has been removed. At a high level:
- Typed Actors (the classic
TypedActorAPI, not Pekko Typed) (#571, PR1969) ActorMaterializerclass and deprecated materializer,ActorMaterializerSettings,IOSettingsandStreamRefSettingsfactory methods (PR2011, PR2137, PR3293)- Deprecated stream operators and methods, including the Future based operators, stream converters,
OverflowStrategy.dropNew,SubstreamCancelStrategy, the oldsplitWhen/splitAfteroverloads,GraphStage.onDownstreamFinish()and the stream testkitprobemethods (PR1958, PR1996, PR2006, PR2012, PR2017, PR2073, PR2129, PR2146, PR2440, PR3292) - Deprecated actor, scheduler, testkit, remote, cluster, cluster-sharding (including old backoff classes and settings), distributed-data, persistence and DNS code (PR1945, PR1959, PR1965, PR1966, PR1969, PR1981, PR1983, PR2018, PR2023, PR2037, PR3289)
pekko.japi.Functionand related classes,FI,JAPIandpekko.japi.Option(PR2007, PR2078, PR2079, PR2193)- Scala version compatibility classes in
pekko.util(such asccompat,FutureConverters,OptionConverters,ExecutionContexts.parasitic) as Pekko now uses the Scala 2.13 standard library equivalents (PR2207, PR2208, PR2212, PR2234, PR2582) - Internal and unused code such as
ReentrantGuard,AbruptIOTerminationException,ActorProcessorand the classic remotingdisassociatemethods (#2160, PR2065, PR2072, PR2074, PR2161, PR3027) - The
ssl-configconfiguration sections (PR2359) - Support for removing Cluster Sharding coordinator data stored by Akka 2.3.x from
RemoveInternalClusterShardingData(PR3608)
Deprecations
Some additional APIs have been deprecated and will be removed in a future release.
org.apache.pekko.dispatch.Futures(#1417, PR3377)Patterns.timeout(PR2050)Source.futurein the Java DSL (PR2593)BalancingDispatcherConfigurator, which is now also marked as internal API (#3384, PR3391)- The
pekko.persistence.dispatchersconfiguration (PR2482)
Dependency Changes
- Java 17 is the minimum supported version
- Scala 2.13.18 and 3.3.9
- netty 4.2.19.Final
- jackson 2.22.4 (pekko-serialization-jackson) and jackson 3.2.4 (pekko-serialization-jackson3)
- aeron 1.53.3 and agrona 2.6.1
- protobuf-java 4.36.2
- lightbend/config 1.4.9
- slf4j 2.0.20
- lz4-java 1.12.1 (
at.yawk.lz4:lz4-java) - zstd-jni 1.5.7-24 (optional, only needed for zstd compression in the Jackson serializers)
- junit-jupiter 6.1.3
- The
ssl-configdependency has been removed
Known Issues
- MergeLatest does not backpressure upstreams and buffers without bound (#3592).