Release Notes (2.0.x)

Apache Pekko 2.0.x releases support Java 17 and above.

2.0.0

Warning

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 as pekko.japi.function.FI and JAPI) in favour of pekko.japi.function.Function and the other pekko.japi.function types. 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, Tuple2 and Scala collections have been replaced with CompletionStage, Optional, pekko.japi.Pair and 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.Unsafe is 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 PEKK as 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 DeletedDurableState for 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.Unsafe to 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.ROOT for toLowerCase/toUpperCase calls (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/BigDecimal in 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 Mailbox object to the fork-join dispatcher, which could permanently damage a ForkJoinPool work queue or stop a mailbox from running again. Mailbox no longer extends ForkJoinTask (#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 LogSource for getClass results on Scala 3, so Logging(system, getClass) compiles (#1538, PR3609)
  • Allow overriding testKit with a val in ScalaTestWithActorTestKit (#1140, PR3610)
  • Keep the StashBufferImpl instrumentation 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_CLASS is now treated as dangerous, like Id.CLASS (PR3304)
  • Resolve, check and parse manifests more carefully in the Jackson serializers (PR3503)
  • New max-decompressed-size limit for Jackson payload decompression and for other compressed payloads (defaults to unlimited for Jackson) (PR3491, PR3502, #3504, PR3515, PR3597)
  • Support unlimited for 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 maxTotalBufferSize to 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 appVersion later (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) and EventsBySliceStartingFromSnapshotsQuery (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 with methods to the typed query EventEnvelope (PR3646)
  • Predefined JsonSerializable and CborSerializable marker traits in pekko-serialization-jackson and pekko-serialization-jackson3, bound to jackson-json and jackson-cbor (PR3649, PR3666)
  • Bind ScalaPB messages to the protobuf serializer when ScalaPB is on the classpath (PR3651)
  • Add SerializedEvent for writing events that are already serialized (PR3650)

Additions

  • Add ActorSystem.terminateAndAwait and ActorSystem.close (PR2096, PR2486)
  • Add UntypedAbstractActorWithStash, UntypedAbstractActorWithUnboundedStash and UntypedAbstractActorWithUnrestrictedStash (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 ReceiveTimeout message (PR3399)
  • Add andThen and compose to pekko.japi.function.Function (#2144, PR2147)
  • Add a throwing boolean supplier, sneakyThrow and OptionalUtil Java utilities (PR2199, PR2218, PR2464)
  • Add CompletionStages utility and make timeoutCompletionStage/afterCompletionStage accept Java Duration (PR2060, PR2063, PR2067)
  • Add StatusReply.fromTry and StatusReply.fromCallable (PR2810, PR2812)
  • Add JournalPersistFailed and JournalPersistRejected signals (PR1961)
  • Add an AsyncWriteJournal option for disabling the Resequencer (PR2027)
  • Add DurableStateBehaviorTestKit (PR3360)
  • PersistenceTestKitReadJournal tag and slice queries support resuming from a TimestampOffset (#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 shutdownActorSystem that 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-runnable configurable and auto-tune it on JDK 25+ (PR2871, PR2890)
  • Support the SO_REUSEPORT socket option (PR2915)
  • Add ByteString.endsWith, indexOf with from and to, and make ByteString.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.source and materializeIntoSource operators (#2222, PR2250, PR1831)
  • Add Sink#count operator (#2182, PR2244)
  • Add onErrorResume (including Java DSL, SubFlow and SubSource variants) and more recover operators for the Java DSL (#2116, PR2120, PR2336, PR2337)
  • Add onErrorContinue operator (#2159, PR2322)
  • Add doOnFirst operator (#2183, PR2363)
  • Add doOnCancel operator (#2374, PR2375)
  • Add gzipDecompress operator, replacing the deprecated gunzip (which has been removed) (PR2406)
  • Add Source.fromOption and mapOption operators (#2408, #2403, PR2413, PR2414)
  • Add Source.items and an array based Source.apply (#2416, PR2424, PR2428, PR2429)
  • Add withContext operators (PR3199)
  • Add an alsoTo overload with configurable cancellation propagation (PR3127)
  • Add supervision strategy support to more operators that accept user functions (groupedWeightedWithin, batch, expand and extrapolate) 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 SubFlow and SubSource final classes and switch the type parameter order of UnfoldResourceSource and UnfoldResourceSourceAsync (PR615, PR616, PR619)
  • Remove the unnecessary empty parameter list from watchTermination (#2376, PR2378)
  • Change Futures#find and other Futures methods to return Java CompletionStage (#2008, PR2009)
  • Stream Java DSL now uses pekko.japi.function types throughout (#2118, PR2143)
  • Fix the Java DSL SourceWithContext/FlowWithContext shape to use pekko.japi.Pair (#2510, PR3388)
  • Replace scala.Tuple2 with pekko.japi.Pair in FSMTransitionHandlerBuilder (PR3378)
  • Replace immutable.Traversable in the public io and stream APIs (PR3467, PR3468)
  • Remove ExecutorServiceFactoryProvider from ThreadPoolConfig (#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 recoverWith and undeprecate the getFirst/getFirstAttribute methods (PR2119, PR3404)
  • Mark public sealed traits and abstract classes with @DoNotInherit (#1270, PR3386)
  • Remove @ApiMayChange from APIs that have proven stable, including the log markers, RotatingKeysSSLEngineProvider, ExternalShardAllocation, RetryFlow, the MaterializerState API 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-config dependency (#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.jdk converters instead of compat libraries (#2126, PR2205, PR2206, PR2236, PR3539)
  • Use -Yfuture-lazy-vals for 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.queue overloads 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.result and multi-byte reads (PR2847, PR2924, PR3427, PR3428, PR3463, PR3471, PR3526)
  • Faster UnsynchronizedByteArrayInputStream usage (PR2300, PR3541)
  • Batch elements across internal async stream boundaries (PR3288, PR3296, #3459, PR3461)
  • Optimize Source.from iterable, Source.future, Source.futureSource and Source.apply for 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.actorRef with 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 TypedActor API, not Pekko Typed) (#571, PR1969)
  • ActorMaterializer class and deprecated materializer, ActorMaterializerSettings, IOSettings and StreamRefSettings factory methods (PR2011, PR2137, PR3293)
  • Deprecated stream operators and methods, including the Future based operators, stream converters, OverflowStrategy.dropNew, SubstreamCancelStrategy, the old splitWhen/splitAfter overloads, GraphStage.onDownstreamFinish() and the stream testkit probe methods (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.Function and related classes, FI, JAPI and pekko.japi.Option (PR2007, PR2078, PR2079, PR2193)
  • Scala version compatibility classes in pekko.util (such as ccompat, 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, ActorProcessor and the classic remoting disassociate methods (#2160, PR2065, PR2072, PR2074, PR2161, PR3027)
  • The ssl-config configuration 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.future in the Java DSL (PR2593)
  • BalancingDispatcherConfigurator, which is now also marked as internal API (#3384, PR3391)
  • The pekko.persistence.dispatchers configuration (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-config dependency has been removed

Known Issues

  • MergeLatest does not backpressure upstreams and buffers without bound (#3592).