Electron App Database File Structure/Code Structure

Hello Electron Community!

Right to the question. I am using sqlite3 in my Electron application, and I was wondering as to where the logical place for the code pertaining to models and migrations to live. I have an image with my current file structure for my application. Thoughts?

Additionally, again pertaining to db usage conventions, where should db initialization and query logic live? As it currently stands, I initialize the db and attach it to the global in main.js on the Browser side , and I query the db on Renderer side with the remote.getGlobal. Any thoughts?

I suppose this is an open ended discussion. All input is welcome. Thanks.


Regarding needing to remote over to query the database, if the entire purpose of your application is to work with the database, I think this is unwise because things on the Browser side are so much harder to debug… I would recommend organizing things logically more like Atom does with only the things that must interact directly with the OS (i.e. the platform specific code) should be on the Browser side and the Renderer side is the vast majority of the application logic (including saving, moving, and deleting files, interacting with git, and all packages).

So I would initialize and query the database both from the Renderer side.


I see. One benefit to having the init of the db in the Browser is that I would only have to init one time for the entire application. Could I accomplish this on the Renderer side? If so, how?

Example of my current code (Browser Side) :

The same way the Atom app does it. They create the atom global by attaching it to window and then in any package or module you can always call atom.config.set() or atom.project.getPaths() or what have you :grinning:

1 Like

I see. This answers my question! Side note though: what about communication between BrowserWindow instances. I am assuming that each BrowserWindow has a separate window. It may very well be that this use case is rare, however, I am curious none the less.

Each window is its own process, so if you want to communicate between windows, you have to come up with your own system for it.

Okay. Now would you suggest using the Browser instance as the glue to such a system?

To communicate between the window processes? No, I’d write all my code in the Renderer. The Browser side is really just there to work with the OS to build the native window, set everything up and hand off to the Renderer. So I would put as much code as is possible on the Renderer side and only if I had no other choice would I put something on the Browser side. I would want to cross that remote border as little as possible. It just simplifies things enormously.

Here’s the contents of the Browser code for Atom:


A total of 9 files at the time of this writing. Here’s the contents of the Renderer code for Atom:

A total of 99 files at the time of this writing.


:smile: Thanks for all the help. It’s been a pleasure talking with you. :smile:


Can you please elaborate a bit more about how to create a global that is accessible in both the browser and the renderer? I’ve tried setting global.db = db in the app’s ready event, but global.db is undefined later on in the rendering side.

My ultimate issue how to do filesystem access from the rendering side. This is where I’d prefer to do it, and where you’ve recommended it be done, but I can’t figure out how. app is a browser-side module (where to get paths) and I can’t get fs to even intialize. I’m using NeDB as a data store, but I seem to only be able to access the filesystem from the browser side.

Any help would be appreciated.

Technically, you can’t create a global that is accessible in both the main process (formerly browser) and the renderer process. The main process is running in one OS process and the renderer process is running in a separate OS process, meaning that you have to use some form of inter-process communication (IPC) to shuttle information between them.

Now, Electron has a few methods of IPC built-in:

But the global that you create will only be directly accessible on one side or the other. The other process will have to access it through a remote proxy or some other such mechanism.

As far as getting access to the file system from the renderer side, you should be able to just simply do:

fs = require 'fs'

text = fs.readFileSync('/some/path/somewhere.txt')

Because Node (and all its built-in libraries) are available on both sides.

I can’t speak to NeDB, I’ve never used it.

1 Like

Thanks for explaining the limitations of the global. That’s a lot more in line with my understanding of process boundaries. Now it makes sense why @john_kelly was using remote to access main’s global.

I’m not able to use fs from the renderer process. I’m using import fs from 'fs' (ES6/Babel) and when I call fs.readdirSync('/') I get the error fs.readdirSync is not a function. But when I do this from it main process it works as expected. I thought I remember seeing references in Electron’s source to a custom fs that deals with the specifics of the ASAR format. Could that be what I’m hitting?

I would prefer to access the filesystem from the renderer process. Any idea what I’m doing wrong? I should also mention I’m using Electron v0.26.0 on OS X 10.10. I’m debugging from a Gulp task that launches electron .


That could definitely be what you’re hitting. Try this instead:

fs = require 'fs-plus`

Or whatever the equivalent is for ES6. Though you should only need to do this when reading files that exist inside the ASAR package. You should be able to use either if you’re reading/writing files that are in the normal file system.

How about performance issue…

Should I write file from renderer processs? Is there any some kind of size limitation advice?

Hey , try accessing fs module from renderer process using remote as mentioned by john. Here is an example this works for me.
var fs = electron.remote.require(‘fs’);

The above line should give you access to fs module. Let me know if it works

While this works it’s not a very good idea, the remote module uses synchronous IPC which means the renderer process will be blocked while waiting for IO to finish in the main process, and then it has to wait while the result is sent back via IPC. If you can use a particular Node API in the main process but not in the renderer then you need to fix your Webpack config or whichever other part of your build system is mucking up regular Node module resolution.

Thanks for the information. Could you please let me know what I need to do in webpack to fix node modules to work in renderer process. I tried “target: electron-renderer” which worked but had issues with component rendering. There were lot of GUI Issues. I am using angular2 + electron. Any help is much appreciated.

@john_kelly The image you have added in your post is not loading can you add the image again.

After reading all the reply, I still don’t understand the file structure to follow for database in electron app.

You can store your database anywhere you want in your application’s folder, the user’s home folder, or a designated place like AppData/ on Windows. The only requirement is that you know where the database is relative to where your app is.