Futureverse

Parallelize your R code by changing one line - and run it anywhere

The hexlogo of the future package. A left-facing arrow with the text future underneath - both in bold style filled with yellow-to-orange vertical gradient. The background is dark blue with teeny star-shaped symbols in distance resembling looking deep out in the universe. The hexlogo is surrounded by a light-blue border.

Futureverse makes your existing R code run in parallel - on your own computer, across machines on your local network, in the cloud, or on a high-performance compute (HPC) cluster. You do not have to restructure your code, and you do not have to think about workers, exporting global variables, or parallel random number generation.

The goal is to lower the barrier so that anyone can speed up their existing R code in a worry-free manner. It is cross-platform and needs no additional setup: the same code runs on MS Windows, macOS, and Linux.

plan(multisession)                        # once, at the top of your script

ys <- lapply(xs, slow_fcn)                # sequential, as before
ys <- lapply(xs, slow_fcn) |> futurize()  # the same, now in parallel

That is the whole idea: you keep your code, and you decide where it runs.

No installation needed to try it: run Futureverse in your browser in the live demo.

What you get

Your code stays your code

Whether you write base R, tidyverse, or foreach, there is no need to switch style or adopt a new set of functions. lapply(), purrr::map(), and foreach() %do% { ... } all parallelize the same way, and so do 47 domain-specific packages on CRAN and Bioconductor, e.g. boot(), glmnet(), and DESeq():

library(futurize)
plan(multisession) # parallelize on local computer

# Sequential and parallel version of base R apply
y <- lapply(X, slow_fcn)
y <- lapply(X, slow_fcn) |> futurize()

# Sequential and parallel version of purrr map
library(purrr)
y <- X |> map(slow_fcn)
y <- X |> map(slow_fcn) |> futurize()

# Sequential and parallel version of foreach
library(foreach)
y <- foreach(x = X) %do% slow_fcn(x)
y <- foreach(x = X) %do% slow_fcn(x) |> futurize()

# Sequential and parallel version of plyr
library(plyr)
ys <- llply(xs, sqrt)
ys <- llply(xs, sqrt) |> futurize()

# Sequential and parallel version of BiocParallel
library(BiocParallel)
ys <- bplapply(xs, sqrt)
ys <- bplapply(xs, sqrt) |> futurize()
library(futurize)
plan(multisession) # parallelize on local computer

library(boot)
b <- boot(city, ratio, R = 999) |> futurize()

library(glmnet)
cv <- cv.glmnet(x, y) |> futurize()

library(caret)
ctrl <- trainControl(method = "cv", number = 10)
model <- train(Species ~ ., data = iris, trControl = ctrl) |> futurize()

library(partykit)
cf <- cforest(dist ~ speed, data = cars) |> futurize()

library(stars)
res <- st_apply(s, MARGIN = 1, FUN = mean) |> futurize()

library(vegan)
md <- mrpp(dune, Management) |> futurize()

library(DESeq2)
ds <- DESeq(ds) |> futurize()

library(SingleCellExperiment)
res <- applySCE(sce, perFeatureQCMetrics) |> futurize()

# Many more ...
library(future)
plan(multisession) # parallelize on local computer

# Evaluate an R expression sequentially
y <- slow_fcn(X[1])

# Evaluate it in parallel in the background
f <- future(slow_fcn(X[1]))
y <- value(f)

See futurize for the full list of supported packages.

It behaves like R, not like a parallel framework

Adding parallelization normally means new ways for things to go wrong. Futureverse removes those hurdles and protects against the common pitfalls at the core of the ecosystem, instead of leaving them to developers and end-users:

  • Output, messages, warnings, and errors work as expected and can be handled with traditional R techniques - regardless of how the code is parallelized
  • Global variables and package dependencies are identified and exported automatically
  • Parallel random number generation is statistically sound, so results are reproducible
  • Progress can be reported in near real-time, even from parallel workers, via progressify and progressr

You decide where it runs - not the package author

The same code runs anywhere. Switching is a single line, and it applies to all future-based code in your session, including code inside packages you did not write, e.g.

plan(sequential)                            # in the current R session
plan(multisession)                          # background R sessions, this machine
plan(cluster, workers = c("n1", "n2"))      # other machines, via SSH
plan(future.batchtools::batchtools_slurm)   # an HPC job scheduler

See Parallel Backends for all available backends, e.g. future.callr, future.mirai, and future.batchtools.

Every backend must pass the Future API conformance tests in future.tests before it can call itself one. Switching backend never changes your results, only where they are computed.

It is not only about speed

Futures also make web interfaces asynchronous: a blocking shiny application can be turned into a non-blocking, responsive experience by resolving expensive computations in the background.

Proven in the wild

Futureverse is not new, and it is not niche. Since the first CRAN release of future in June 2015, it has become part of the foundation that a large share of the R ecosystem is built on.

~1,250 CRAN packages rely on future, directly or indirectly - 5.2% of all of CRAN

top-0.6% most downloaded package on CRAN

>500 direct reverse dependencies re-checked before every single release

since 2015 and 100% backward compatible - no breaking updates

As of July 2026, from the future reverse-dependency checks and CRAN download logs.

It is used across statistics, machine learning, forecasting, genomics, epidemiology, clinical trials, ecology, finance, and geospatial analysis - by packages such as Seurat, mlr3, targets, EpiNow2, and shiny.

See Real-World Use & Statistics for examples, and Quality, Validation & Maintenance for how correctness is validated.

Which part is for you?

If you analyze data

Add plan(multisession) and |> futurize() and your existing scripts run in parallel. If a package you use already builds on futures, a single plan() call is enough - no code change at all.

Start with the tutorials →

If you write packages

Write your parallel code once against the Future API and it runs on every backend - present and future - without you testing against any of them. Backend authors validate their own backends against the future.tests conformance suite, so you do not have to.

Overview of all packages →

Get started

install.packages("futurize")

Then:

They are still here, fully supported, and are not going anywhere. future.apply, furrr, and doFuture are now the workhorses operating in the background for futurize, so you can keep using them directly, adopt futurize(), or mix both.

References

Bengtsson, Henrik. 2021. A Unifying Framework for Parallel and Distributed Processing in R using Futures.” The R Journal, ahead of print. https://doi.org/10.32614/RJ-2021-048.
Bengtsson, Henrik. 2026. A Unified Approach to Concurrent, Parallel Map-Reduce in R using Futures. https://arxiv.org/abs/2601.17578.