You won’t be updating the static VBOs every frame!!!
Never do back-face culling on the cpu!
Here’s how modern graphics works: you have a VBO for each mesh (1-6000 tris). You upload those meshes on startup (OpenGL will send them to VRAM). Then, on every frame, you tell the gpu: “use this texture, this shader, and draw this whole mesh”. Notice “whole mesh”. The gpu will transform+cull the mesh so fast, that your cpu-based culling would have computed only 1%-10% of the triangles in the same time, not to mention the PCIe bandwidth you’d waste to send the geometry would be making the game even slower.
Modern gpus can compute and cull 300-700 million triangles/s . On a 3GHz cpu, you can do less than 5% of that.
Of course, it won’t be nice to tell the gpu to draw the whole scene. You’d want to keep some of that processing power invested in the fragment-shaders. Thus, segment your scene into medium-sized meshes, of 5000-60000 triangles, and do frustum-culling on them. Or even better, group objects in octree-like fashion, where you can cull whole collections of such medium-sized meshes with just one frustum-culling test.