The {geos} package provides better performance and lower memory footprint compared to {sf} for processing vector data in a planar coordinate system.

Code
library("sf")
library("geos")
set.seed(1)

Buffer

n = 100000
df = data.frame(x = rnorm(n), y = rnorm(n))
pts_sf = st_as_sf(df, coords = c("x", "y"))
pts_sf = st_as_sfc(pts_sf)
pts_geos = as_geos_geometry(pts_sf)
system.time({
  b_sf = st_buffer(pts_sf, 50, nQuadSegs = 30)
})
##    user  system elapsed 
##    3.09    0.20    3.30
system.time({
  b_geos = geos_buffer(pts_geos, 50, params = geos_buffer_params(quad_segs = 30))
})
##    user  system elapsed 
##    1.63    0.04    1.65
idx = sample(length(b_sf), size = 1000)
plot(b_sf[idx], axes = TRUE, main = "Buffers")

Centroid

system.time({
  c_sf = st_centroid(b_sf)
})
##    user  system elapsed 
##    1.03    0.11    1.14
system.time({
  c_geos = geos_centroid(b_geos)
})
##    user  system elapsed 
##    0.21    0.02    0.23
plot(c_sf, axes = TRUE, pch = 20, main = "Centroids")

Intersects

poly_sf = st_as_sfc("POINT(0 0)")
poly_sf = st_buffer(poly_sf, dist = 1)
poly_geos = as_geos_geometry(poly_sf)
system.time({
  i_sf = st_intersects(pts_sf, poly_sf, sparse = FALSE, prepared = TRUE)
})
##    user  system elapsed 
##    0.30    0.03    0.33
system.time({
  i_geos = geos_prepared_intersects(pts_geos, poly_geos)
})
##    user  system elapsed 
##    0.04    0.01    0.06
all(i_sf == i_geos)
## [1] TRUE
summary(as.vector(i_sf))
##    Mode   FALSE    TRUE 
## logical   60621   39379