To help reduce lag in a large map, see Game Content Streaming. This feature loads in the surrounding of the Client as the character approaches it at a certain distance. However, there are certain limitations and conditions you must meet in order to make it run smoothly.
Transparency is never the way to go and should only ever be used for stylistic purposes. Any part that is neither fully opaque nor fully transparent will require the GPU to merge the colors making up that foreground part with the colors of whatever is behind that part. I would assume ROBLOX’s engine has logic to handle fully transparent parts that would optimize this, but your best bet it to simply set the elements’ Parents to nil. This will keep them in memory, but it will reduce CPU and GPU loads because the game doesn’t have to think about those parts. Because they are still in memory, they can be re-parented to the workspace fairly painlessly.
To follow up on what @Wicked_Wlzard suggested, StreamingEnabled/content streaming is a convenient (if you’re used to working with it) memory management solution because of its lower-level access. StreamingEnabled will be able to adapt better to devices based on their capabilities because, well, it can actually see what resources are available to it, whereas very-little-to-none of that information is inherently available to developers. However, content streaming creates an unstable runtime environment that only a handful of developers on the platform seem to want to tolerate. Moreover, the actual handling of elements is not well-documented, which can make it more difficult to ascertain the current gamestate.
Regardless of your approach, though, it is always good practice to remove game assets from the environment when they are not in use; for instance, removing the interior of a house when the player is not in that house. This sort of implementation is more context-based, though, so it can be hard to say what the best way to implement it would be. For elements with concrete entry and exit points, trigger zones on either sides of those points could suffice. For less confined elements, checking the player’s proximity to them periodically could work, instead. For your chunk method, I would think your chunks would be associated with some sort of grid, yes? In that case, as the player moves through the grid, elect to remove chunks that are a certain distance from the current chunk the player is in. You could either use the Magnitude from the player’s position relative to the epicenter of each chunk, or you could use a 2D array and base your distances off the occupied chunk’s X-Y to the fringe chunks’ X-Ys.
If memory does become an issue, manually destroying elements instead of parenting them to nil will free up their resources eventually. A fully-manual implementation will require more developer input, but it will allow for a more controlled environment that knows where all of its components are. If the majority of the elements of your game are either decorations or are not interacted with by client-side code, StreamingEnabled is probably your best bet. If the client needs to interact with many elements or needs to know where many elements are at any given time, you will likely need a more nuanced, more manual memory management implementation.